PHP 5'te, self
ve ile arasındaki fark $this
nedir?
Her biri ne zaman uygundur?
PHP 5'te, self
ve ile arasındaki fark $this
nedir?
Her biri ne zaman uygundur?
Yanıtlar:
$this
Geçerli nesneye başvurmak için kullanın .self
Geçerli sınıfa başvurmak için kullanın . Başka bir deyişle,$this->member
statik olmayan üyelerself::$member
için kullanın , statik üyeler için kullanın .
İşte bir örnek , doğru kullanımı $this
ve self
sigara statik ve statik üye değişkenler için:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}
new X();
?>
Burada bir örnek , yanlış kullanımı $this
ve self
dışı statik ve statik üye değişkenler için:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo self::$non_static_member . ' '
. $this->static_member;
}
}
new X();
?>
İşte bir örnek polimorfizm ile $this
üye işlevleri için:
<?php
class X {
function foo() {
echo 'X::foo()';
}
function bar() {
$this->foo();
}
}
class Y extends X {
function foo() {
echo 'Y::foo()';
}
}
$x = new Y();
$x->bar();
?>
Üye işlevleri için kullanarak polimorfik davranışı bastırmanın bir örneği self
:
<?php
class X {
function foo() {
echo 'X::foo()';
}
function bar() {
self::foo();
}
}
class Y extends X {
function foo() {
echo 'Y::foo()';
}
}
$x = new Y();
$x->bar();
?>
Fikir olmasıdır
$this->foo()
çağrılarıfoo()
geçerli nesnenin tam tür ne olursa olsun üyesi fonksiyonunu. Nesne varsatype X
, bu nedenle çağırırX::foo()
. Nesne varsa,type Y
çağırırY::foo()
. Ama self :: foo ()X::foo()
ile her zaman çağrılır.
Gönderen http://www.phpbuilder.com/board/showthread.php?t=10354489 :
self
kapsam çözümleme operatörü ile birlikte kullanılır ::
; bu hem statik hem de statik olmayan bağlamlarda yapılabilir. Ayrıca, $this
statik yöntemleri çağırmak için tamamen yasaldır (ancak referans alanlarına değil).
$this::
?
Anahtar kelime kendinden gelmez DEĞİL en azından bir şekilde, 'Geçerli sınıfa' için sadece işaret ettiğini statik üyelerine kısıtlar sizi. Statik olmayan bir üye bağlamında , geçerli nesne için self
vtable'ı (vtable'da wiki'ye bakın ) atlamanın bir yolunu da sağlar . parent::methodName()
Bir işlevin ebeveyn sürümünü çağırmak için kullanabileceğiniz gibi self::methodName()
, bir yöntemin geçerli sınıf uygulamasını çağırmak için de arayabilirsiniz.
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getTitle() {
return $this->getName()." the person";
}
public function sayHello() {
echo "Hello, I'm ".$this->getTitle()."<br/>";
}
public function sayGoodbye() {
echo "Goodbye from ".self::getTitle()."<br/>";
}
}
class Geek extends Person {
public function __construct($name) {
parent::__construct($name);
}
public function getTitle() {
return $this->getName()." the geek";
}
}
$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();
Bu çıktı:
Merhaba, ben Ludwig olan inek
Ludwig kişiden elveda
sayHello()
$this
işaretçiyi kullanır , böylece vtable çağırmaya çağrılır Geek::getTitle()
.
sayGoodbye()
kullanır self::getTitle()
, böylece vtable kullanılmaz ve Person::getTitle()
çağrılır. Her iki durumda da, somutlaştırılmış bir nesnenin yöntemiyle uğraşıyoruz $this
ve çağrılan işlevler içindeki işaretçiye erişebiliyoruz .
self
" / "sınıf tanımı olarak anlaşılabilir, bu sınıf," nesnenin sınıfının "yanı sıra" gerçekte "nin gerçek bir parçasıdır static
.
$this::
?
$this::
; tüm olası durumlar zaten daha yaygın kullanılan sözdizimleri tarafından kapsanmaktadır. Ne demek istediğini bağlı olarak, kullanım $this->
, self::
veya static::
.
KULLANMAYIN self::
, kullanınstatic::
Benliğin başka bir yönü daha var: söz etmeye değer. Can sıkıcı bir self::
şekilde, icra noktasında değil tanım noktasında kapsamı ifade eder . Bu basit sınıfı iki yöntemle düşünün:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
Aradığımızda Person::status()
"Kişi yaşıyor" göreceğiz. Şimdi, bundan miras kalan bir sınıf oluşturduğumuzda ne olacağını düşünün:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Arayan Deceased::status()
biz "Kişi ölmüş" görmeyi beklediğiniz ancak gördüğümüz çağrı zaman kapsamı orijinal yöntem tanımını içerdiği "Kişi hayatta" dır self::getStatus()
tanımlandı.
PHP 5.3'ün bir çözümü var. static::
çözünürlük operatörü uygular denir sınıfın kapsamına kaçınılmazdır söyleyerek bir fantezi yolu olan "geç statik bağlama". Çizgi değiştirin status()
etmek static::getStatus()
ve sonuçları ne beklediğiniz vardır. PHP'nin eski sürümlerinde bunu yapmak için bir çamur bulmanız gerekecek.
PHP Belgelerine Bakın
Bu yüzden soruyu sorulduğu gibi değil ...
$this->
geçerli nesneyi (bir sınıf örneği) static::
belirtirken, bir sınıfı belirtir
getStatus
Metodu bir sınıf için değil, bir sınıf örneği için çağırdığım yöntem olarak görüyorum .
self::
, bunu daha az alabilirsiniz kafa karıştırıcı bir şekilde, belirli bir sınıf adı kullanarak, örn MyClass::
.
Gerçekten biz bahsederken bahsettiğinizi anlamak için self
karşı $this
, aslında kavramsal ve pratik bir düzeyde neler içine kazmak gerekir. Cevapların hiçbirinin bunu uygun şekilde yaptığını gerçekten hissetmiyorum, işte benim girişimim.
Bir sınıfın ve bir nesnenin ne olduğu hakkında konuşarak başlayalım .
Peki, ne olduğunu bir sınıf ? Birçok insan bunu bir plan veya bir nesne için şablon olarak tanımlar . Aslında, PHP Hakkında Sınıflar Hakkında Buradan daha fazla bilgi edinebilirsiniz . Ve bir dereceye kadar gerçekten böyle. Bir sınıfa bakalım:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
Anlayacağınız gibi, söz konusu sınıfta bir özellik ve çağrılan $name
bir yöntem (işlev) vardır sayHello()
.
O var çok dikkat etmek önemlidir sınıf statik bir yapıdır. Yani sınıf Person
, bir kez tanımlandığında, baktığınız her yerde her zaman aynıdır.
Öte yandan bir nesne Sınıf örneği olarak adlandırılan şeydir . Bunun anlamı, sınıfın "taslağını" alıp dinamik bir kopya oluşturmak için kullanmamızdır. Bu kopya artık özel olarak depolandığı değişkene bağlıdır. Bu nedenle, bir örnekte yapılan değişiklikler o örnek için yereldir.
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
İşleç kullanarak bir sınıfın yeni örneklerini yaratırız new
.
Bu nedenle, bir Sınıfın küresel bir yapı ve bir Nesnenin yerel bir yapı olduğunu söylüyoruz. O komik ->
sözdizimi için endişelenme , biraz buna gireceğiz.
Bahsetmemiz gereken diğer bir şey de, bir örneğin belirli bir sınıf olup olmadığını kontrol edebilmemizdir instanceof
: örneğin sınıf veya alt öğesi kullanılarak yapılmışsa $bob instanceof Person
, bir boole döndürür .$bob
Person
Person
Öyleyse bir sınıfın gerçekte ne içerdiğine biraz bakalım. Bir sınıfın içerdiği 5 tür "şey" vardır:
Özellikler - Bunları her örneğin içereceği değişkenler olarak düşünün.
class Foo {
public $bar = 1;
}
Statik Özellikler - Bunları sınıf düzeyinde paylaşılan değişkenler olarak düşünün. Yani her örnek tarafından asla kopyalanmıyorlar.
class Foo {
public static $bar = 1;
}
Yöntemler - Bunlar, her bir örneğin içereceği (ve örneklerde çalışacağı) işlevlerdir.
class Foo {
public function bar() {}
}
Statik Yöntemler - Bunlar, tüm sınıf boyunca paylaşılan işlevlerdir. Onlar do değil örneklerinde, ancak bunun yerine sadece statik özelliklerine çalışırlar.
class Foo {
public static function bar() {}
}
Sabitler - Sınıf çözümlenmiş sabitler. Burada daha derine inmemek, ancak tamlık için eklemek:
class Foo {
const BAR = 1;
}
Yani temel olarak, yaklaşık "ipuçlarını" kullanarak sınıf ve nesne konteyner hakkında bilgi depolamak statik bilgiler paylaşılır (ve dolayısıyla statik) olmadığını (ve dolayısıyla dinamik) olup olmadığını belirlemek.
Bir yöntemin içinde, bir nesnenin örneği $this
değişken tarafından temsil edilir . Bu nesnenin geçerli durumu oradadır ve herhangi bir özelliğin mutasyona uğratılması (değiştirilmesi), o örnekte bir değişikliğe neden olur (ancak diğerleri değil).
Bir yöntem statik olarak çağrılırsa, $this
değişken tanımlanmaz . Bunun nedeni, statik çağrı ile ilişkilendirilmiş bir örnek olmamasıdır.
Burada ilginç olan, statik çağrıların nasıl yapıldığıdır. Devlete nasıl eriştiğimiz hakkında konuşalım:
Şimdi bu durumu kaydettiğimize göre, ona erişmemiz gerekiyor. Bu biraz alabilirsiniz zor (veya yolu daha biraz daha), bu yüzden iki bakış açıları içine bu bölelim: Bir örnek / sınıfın dışından (normal fonksiyon çağrısından veya genel kapsamından söylemek) ve bir örneğinin iç / class (nesne üzerindeki bir yöntemden).
Bir örnek / sınıfın dışından, kurallarımız oldukça basit ve öngörülebilirdir. İki operatörünüz var ve her biri bize bir örnekle veya bir sınıf statikiyle uğraştığımızı hemen söylüyor:
->
- object-operator - Bu, her zaman bir örneğe erişirken kullanılır.
$bob = new Person;
echo $bob->name;
Aramanın Person->foo
mantıklı olmadığını belirtmek önemlidir (çünkü Person
bir sınıf değil, bir sınıftır). Bu nedenle, bu bir ayrıştırma hatasıdır.
::
- scope-Resolution-operator - Bu her zaman bir Class statik özelliğine veya yöntemine erişmek için kullanılır.
echo Foo::bar()
Ayrıca, bir nesne üzerindeki statik yöntemi aynı şekilde çağırabiliriz:
echo $foo::bar()
Bunu dışarıdan yaptığımızda , nesnenin örneğinin yöntemden gizlendiğine dikkat etmek son derece önemlidir . Yani koşu ile tam olarak aynı:bar()
$class = get_class($foo);
$class::bar();
Bu nedenle, $this
statik çağrıda tanımlanmaz.
Burada işler biraz değişiyor. Aynı operatörler kullanılır, ancak anlamları önemli ölçüde bulanıklaşır.
Nesne operatör ->
hala nesnenin örnek durumuna arama yapmak için kullanılır.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Nesne operatörünü kullanarak bar()
yöntemi çağırma $foo
(örneği Foo
):$foo->bar()
örneğin sürümü ile sonuçlanır $a
.
Yani böyle bekliyoruz.
Yine de ::
operatörün anlamı değişir. Geçerli işleve yapılan çağrının bağlamına bağlıdır:
Statik bir bağlam içinde
Statik bir bağlam içinde, kullanılarak yapılan çağrılar ::
da statik olacaktır. Bir örneğe bakalım:
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
Arama Foo::bar()
arayacak baz()
statik yöntemini ve dolayısıyla $this
edecek değil doldurulur. PHP'nin son sürümlerinde (5.3+) bunun bir E_STRICT
hata tetikleyeceğini belirtmek gerekir , çünkü statik olmayan yöntemleri statik olarak çağırıyoruz.
Bir örnek bağlamında
Öte yandan bir örnek bağlamında, ::
çağrının alıcısına (çağırdığımız yönteme) bağlıdır. Yöntem olarak tanımlanırsa static
, statik bir çağrı kullanır. Değilse, örnek bilgilerini iletir.
Dolayısıyla, yukarıdaki koda bakıldığında , "statik" çağrı bir örnek bağlamında gerçekleştiğinden çağrı $foo->bar()
geri döner true
.
Mantıklı olmak? Öyle düşünmemiştim. Kafa karıştırıcı.
Sınıf adlarını kullanarak her şeyi birbirine bağlamak oldukça kirli olduğundan, PHP kapsam çözümlemesini kolaylaştırmak için 3 temel "kısayol" anahtar kelimesi sağlar.
self
- Bu, geçerli sınıf adını ifade eder. Yani self::baz()
aynıdır Foo::baz()
içinde Foo
sınıfı (Üzerinde herhangi yöntemi).
parent
- Bu, geçerli sınıfın üst öğesini ifade eder.
static
- Bu çağrılan sınıfı ifade eder. Kalıtım sayesinde, alt sınıflar yöntemleri ve statik özellikleri geçersiz kılabilir. Bu yüzden onları static
sınıf adı yerine kullanarak çağırmak, geçerli düzey yerine çağrının nereden geldiğini çözmemize olanak tanır.
Bunu anlamanın en kolay yolu bazı örneklere bakmaya başlamaktır. Bir sınıf seçelim:
class Person {
public static $number = 0;
public $id = 0;
public function __construct() {
self::$number++;
$this->id = self::$number;
}
public $name = "";
public function getName() {
return $this->name;
}
public function getId() {
return $this->id;
}
}
class Child extends Person {
public $age = 0;
public function __construct($age) {
$this->age = $age;
parent::__construct();
}
public function getName() {
return 'child: ' . parent::getName();
}
}
Şimdi burada da mirasa bakıyoruz. Bir an için bunun kötü bir nesne modeli olduğunu göz ardı edin, ancak bununla oynadığımızda ne olduğuna bakalım:
$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3
Yani kimlik sayacı hem örnekler hem de çocuklar arasında paylaşılır (çünkü self
ona erişmek için kullanıyoruz . Kullanırsak static
, alt sınıfta geçersiz kılabiliriz).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Yönetmekte olduğumuz o Not Person::getName()
örneği yöntemini her seferinde . Ama bunu parent::getName()
vakalardan birinde (çocuk vakası) yapmak için kullanıyoruz. Bu yaklaşımı güçlü kılan da budur.
Çağıran bağlamın, bir örneğin kullanılıp kullanılmadığını belirleyen şey olduğunu unutmayın. Bu nedenle:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Her zaman doğru değildir .
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Şimdi burada gerçekten garip. Farklı bir sınıf çağırıyoruz, ancak yönteme $this
aktarılanFoo::isFoo()
$bar
.
Bu, her türlü hataya ve kavramsal WTF-ery'ye neden olabilir. Çok kaçınarak öneririm Yani ::
(bu üç sanal "kestirme" anahtar kelimeler dışında bir şey üzerinde örnek yöntemleri içinden operatörü static
, self
veparent
).
Statik yöntemlerin ve özelliklerin herkes tarafından paylaşıldığını unutmayın. Bu onları temelde küresel değişkenler yapar. Globaller ile gelen aynı problemlerle. Bu yüzden, gerçekten küresel olmanızdan hoşlanmadıkça, bilgileri statik yöntemlerde / özelliklerde depolamakta tereddüt ederdim.
Genel olarak Geç Statik Bağlama olarak bilinen şeyi kullanmak static
yerine kullanmak istersiniz self
. Ama çok kullanmak her zaman" diyerek aynı şey olmadığını not static
yerine self
yerine. Gerçekten kısa görüşlü olduğunu, durdurma ve yaptığınız ve bunu geçersiz kılmak için muktedir çocuk sınıfları istiyorsanız düşünmek istiyorum çağrısı düşünmek çözülmesi statik aramak.
Çok kötü, geri dön ve oku. Çok uzun olabilir, ama bu çok uzun çünkü bu karmaşık bir konu
Tamam iyi. Kısacası, sınıf içindeki geçerli sınıf adınaself
başvurmak için kullanılır ; burada , geçerli nesne örneğini ifade eder . Not bir kopyasıdır / kısa kesilmiş yapıştırın. Sınıf adınızla güvenle değiştirebilirsiniz ve iyi çalışır. Ancak önceden belirlenemeyen dinamik bir değişkendir (hatta sınıfınız bile olmayabilir).$this
self
$this
Nesne operatörü ( ->
) kullanılıyorsa , her zaman bir örnekle uğraştığınızı bilirsiniz. Scope-Resolution-operatörü kullanılıyorsa ( ::
), bağlam hakkında daha fazla bilgiye ihtiyacınız vardır (zaten bir nesne bağlamında mıyız? Bir nesnenin dışında mıyız? Vb.).
$this
"Katı Standartlar" ı takip ederseniz ve statik olarak statik olarak tanımlanmayan yöntemleri statik olarak çağırmazsanız tanımlanmayacaktır. Burada açıkladığınız sonucu görüyorum: 3v4l.org/WeHVM Kabul etti, gerçekten garip.
Foo::isFoo()
Statik olarak adlandırıldığı $this
gibi tanımlanmayacaktır. Bence bu daha sezgisel bir davranış. - Eğer uzatılacaksa başka bir sonuç verilir . Daha sonra çağrı aslında örnek bağlamı içinde olacaktır (PHP7'ye özgü değildir). Bar
Foo
Foo::isFoo()
self
($ self değil) , sınıfın geçerli örneğine atıfta bulunduğu sınıf türünü$this
belirtir . statik üye değişkenlerine erişmenizi sağlamak için statik üye işlevlerinde kullanım içindir. statik olmayan üye işlevlerinde kullanılır ve üye işlevinin çağrıldığı sınıf örneğine başvurudır.self
$this
Çünkü this
bir nesne, onu şöyle kullanırsınız:$this->member
Çünkü self
bir nesne değil, otomatik olarak geçerli sınıfa başvuran bir tür temelde, bunu gibi kullanın:self::member
$this->
sınıf değişkenlerinin (üye değişkenler) veya yöntemlerin belirli bir örneğini belirtmek için kullanılır.
Example:
$derek = new Person();
$ derek artık Kişinin özel bir örneğidir. Her Kişinin adı ve soyadı vardır, ancak $ derek'in belirli bir adı ve soyadı vardır (Derek Martin). $ Derek örneğinde bunlara $ this-> first_name ve $ this-> last_name diyebiliriz
ClassName :: bu sınıf türünü ve statik değişkenlerini, statik yöntemleri ifade etmek için kullanılır. Eğer yardımcı olursa, zihinsel olarak "statik" kelimesini "paylaşılan" ile değiştirebilirsiniz. Paylaşıldıkları için, belirli bir örneği (paylaşılmayan) ifade eden $ this anlamına gelemezler. Statik Değişkenler (yani statik $ db_connection) bir nesne türünün tüm örnekleri arasında paylaşılabilir. Örneğin, tüm veritabanı nesneleri tek bir bağlantıyı paylaşır (statik $ bağlantısı).
Statik Değişkenler Örnek: Tek üye değişkenli bir veritabanı sınıfımız olduğunu varsayalım: static $ num_connections; Şimdi bunu yapıcıya koyun:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Tıpkı nesnelerin yapıcıları olduğu gibi, nesne öldüğünde veya ayarlanmadığında yürütülen yıkıcılara da sahiptir:
function __destruct()
{
$num_connections--;
}
Her yeni örnek oluşturduğumuzda, bağlantı sayacımızı bir arttırır. Bir örneği her yok ettiğimizde veya durdurduğumuzda, bağlantı sayacını bir azaltacaktır. Bu şekilde, kullandığımız veritabanı nesnesinin örnek sayısını izleyebiliriz:
echo DB::num_connections;
$ Num_connections statik (paylaşımlı) olduğundan, toplam etkin veritabanı nesnesi sayısını yansıtır. Bir veritabanı sınıfının tüm örnekleri arasında veritabanı bağlantılarını paylaşmak için kullanılan bu tekniği görmüş olabilirsiniz. Bu, veritabanı bağlantısı oluşturmanın uzun sürdüğü için yapılır, bu yüzden sadece bir tane oluşturmak ve paylaşmak en iyisidir (buna Tekli Desen denir).
Statik Yöntemler (örn. Public static View :: format_phone_number ($ digits)), bu nesnelerden birini ilk örneklemeden OLMADAN kullanılabilir (yani dahili olarak $ this anlamına gelmez).
Statik Yöntem Örneği:
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).' '.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
Gördüğünüz gibi, prettyName genel statik işlevi nesne hakkında hiçbir şey bilmiyor. Sadece bir nesnenin parçası olmayan normal bir işlev gibi, ilettiğiniz parametrelerle çalışır. Öyleyse, neden nesnenin bir parçası olarak olmasaydık, neden rahatsız edelim ki?
SELF :: Başvurmak istediğiniz statik yönteme sahip nesnenin dışında kod yazıyorsanız, nesneyi View :: format_phone_number ($ phone_number) adını kullanarak çağırmalısınız; Eğer kodlama yapıyorsanız içine sen olabilir başvurmak isteyen statik yöntem vardır nesne ya nesnenin adı Görüntüle :: format_phone_number ($ pn) kullanın VEYA kendini :: format_phone_number ($ pn) kullanabileceğiniz kısayol
Statik değişkenler için de aynı şey geçerlidir: Örnek: View :: templates_path ve self :: templates_path
DB sınıfının içinde, başka bir nesnenin statik yöntemine başvuruyor olsaydık , nesnenin adını kullanırdık: Örnek: Session :: getUsersOnline ();
Ancak DB sınıfı kendi statik değişkenine başvurmak isterse, sadece self derdi: Örnek: self :: connection;
Umarım işleri temizler :)
$
işaret kullanmanız gerekir . Örneğinself::$templates_path
Gönderen bu blog yayınında :
self
şu anki sınıfı ifade ederself
statik işlevleri çağırmak ve statik üye değişkenlere başvurmak için kullanılabilirself
statik fonksiyonların içinde kullanılabilirself
ayrıca vtable'ı atlayarak polimorfik davranışı kapatabilir$this
mevcut nesneyi ifade eder$this
statik fonksiyonları çağırmak için kullanılabilir$this
statik üye değişkenleri çağırmak için kullanılmamalıdır.self
Bunun yerine kullanın .$this
statik fonksiyonlar içinde kullanılamaz
PHP'de, statik özelliklere ve yöntemlere erişmek için self anahtar sözcüğünü kullanırsınız.
Sorun, statik olarak bildirilip bildirilmediğine bakılmaksızın $this->method()
, self::method()
herhangi bir yerle değiştirebilmenizdir method()
. Peki hangisini kullanmalısın?
Bu kodu düşünün:
class ParentClass {
function test() {
self::who(); // will output 'parent'
$this->who(); // will output 'child'
}
function who() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function who() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
Bu örnekte, nesnenin sahip olduğu sınıfa bağlı olarak , self::who()
her zaman 'üst öğe' çıktısı verilir $this->who()
.
Şimdi kendiliğin çağrıldığı sınıfa, mevcut nesnenin sınıfına$this
atıfta bulunduğunu görebiliriz .
Bu nedenle, benliği yalnızca $this
kullanılabilir olmadığında veya alt sınıfların geçerli yöntemin üzerine yazmasına izin vermek istemediğinizde kullanmalısınız.
Sınıf tanımının içinde $this
geçerli nesneye, self
geçerli sınıfa atıfta bulunur.
Kullanarak bir sınıf öğesine self
başvurmak ve kullanarak bir nesne öğesine başvurmak gerekir $this
.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Statik olmayan ve statik üye değişkenler için $ this ve self öğelerinin doğru kullanımına bir örnek:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}
new X();
?>
Http://www.php.net/manual/en/language.oop5.static.php'ye göre yok $self
. Yalnızca $this
, sınıfın geçerli örneğine (nesne) ve kendinin bir sınıfının statik üyelerine atıfta bulunmak için kullanılabilir. Bir nesne örneği ile bir sınıf arasındaki fark burada devreye girer.
Sorunun, sınıfın statik üyesini arayarak çağırabilip çağıramadığına inanıyorum ClassName::staticMember
. Soru, kullanma self::classmember
ve kullanma arasındaki farkın ne olduğuydı$this->classmember
?
Örneğin, aşağıdaki örneklerin her ikisi de kullansanız self::
da,$this->
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
$this->name = $new_name;
$this->address = $new_address;
}
}
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
self::$name = $new_name;
self::$address = $new_address;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
mevcut sınıfı ifade eder (içinde denir),
$this
geçerli nesneyi ifade eder. Benlik yerine statik kullanabilirsiniz. Örneğe bakın:
class ParentClass {
function test() {
self::which(); // output 'parent'
$this->which(); // output 'child'
}
function which() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function which() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
Çıktı: ebeveyn çocuk
$this
geçerli nesneyi ifade eder.static
geçerli nesneyi ifade eder.self
, tanımlandığı sınıfın aynısıdır.parent
, tam olarak tanımlandığı sınıfın üst öğesini belirtir.Aşırı yüklemeyi gösteren aşağıdaki örneğe bakın.
<?php
class A {
public static function newStaticClass()
{
return new static;
}
public static function newSelfClass()
{
return new self;
}
public function newThisClass()
{
return new $this;
}
}
class B extends A
{
public function newParentClass()
{
return new parent;
}
}
$b = new B;
var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A
class C extends B
{
public static function newSelfClass()
{
return new self;
}
}
$c = new C;
var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"
Çoğu zaman geçerli sınıfa başvurmak istiyorsunuz, bu yüzden static
veya kullanıyorsunuz $this
. Bununla birlikte, ihtiyacınız olan zamanlar vardır, self
çünkü orijinal sınıfı ne genişletirse genişletsin istersiniz. (Çok, Çok seyrek)
Burada hiç kimse performanslardan bahsetmediği için, burada yaptığım küçük bir kriter var (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
Bunlar 2 000 000 çalıştırmanın sonuçlarıdır ve işte kullandığım kod:
<?php
require '../vendor/autoload.php';
// My small class to do benchmarks
// All it does is looping over every test x times and record the
// time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);
class Foo
{
public function calling_this()
{
$this->called();
}
public function calling_self()
{
self::called();
}
public function calling_static()
{
static::called();
}
public static function called()
{
}
}
$b->add('$this->', function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::', function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });
$b->run();
1 / 2e9 s = 0.5 ns
bu günlerde yaklaşık 1 işlemci saat döngüsü almalıdır
use
tbh anahtar kelimesini kullanmadığımı bilmiyorum , ancak artık bir karşılaştırmayı yeniden yapmak için PHP'm yok ve gerçekten yeniden yüklemek gibi hissetmiyorum.
Aynı soruya rastladım ve basit cevap:
$this
sınıfın bir örneğini gerektirirself::
değilKullandığınız zaman statik yöntemler veya statik özelliklerini ve sınıfın bir nesnesi kalmadan onları aramak istediğiniz kullanmak gerekir örneği self:
, çünkü onları aramak için $this
her zaman oluşturulacak nesne üzerinde gerektirir.
$this
geçerli sınıf nesnesini, self
geçerli sınıf (nesne değil) anlamına gelir. Sınıf, nesnenin planıdır. Yani bir sınıf tanımlarsınız, ama nesneler inşa edersiniz.
Yani diğer bir deyişle, kullanımda self for static
vethis for none-static members or methods
.
çocuk / ebeveyn senaryosunda self / parent
da çoğunlukla çocuk ve ebeveyn sınıfı üyelerini ve yöntemlerini tanımlamak için kullanılır.
Ayrıca o $this::
zamandan beri henüz tartışılmadı.
Sadece bilgi amaçlı olarak, PHP 5.3'ten itibaren, geçerli kapsam değerini elde etmek için somut nesnelerle uğraşırken, aksine static::
, alternatif olarak kullanılabilir $this::
.
class Foo
{
const NAME = 'Foo';
//Always Foo::NAME (Foo) due to self
protected static $staticName = self::NAME;
public function __construct()
{
echo $this::NAME;
}
public function getStaticName()
{
echo $this::$staticName;
}
}
class Bar extends Foo
{
const NAME = 'FooBar';
/**
* override getStaticName to output Bar::NAME
*/
public function getStaticName()
{
$this::$staticName = $this::NAME;
parent::getStaticName();
}
}
$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar
Yukarıdaki kodu kullanmak yaygın veya önerilen bir uygulama değildir, sadece kullanımını göstermek ve bir "Biliyor muydunuz?" Orijinal posterin sorusuna referansla.
Ayrıca kullanımını temsil eder $object::CONSTANT
, örneğin echo $foo::NAME;
karşı$this::NAME;
Durum 1: Kullanım self
Sınıf sabitleri için kullanılabilir
class classA { sabit FIXED_NUMBER = 4; öz :: POUNDS_TO_KILOGRAMS }
Sınıf dışında aramak istiyorsanız classA::POUNDS_TO_KILOGRAMS
, sabitlere erişmek için
Durum 2: Statik özellikler için
sınıf classC { genel işlev __construct () { öz :: $ _ sayaç ++; $ this-> num = self :: $ _ counter; } }
Php.net göre orada bu bağlamda üç özel anahtar kelimeler: self
, parent
ve static
. Sınıf tanımının içinden özelliklere veya yöntemlere erişmek için kullanılırlar.
$this
diğer yandan, bu sınıfa erişilebilir olduğu sürece herhangi bir sınıfın örneğini ve yöntemlerini çağırmak için kullanılır.
self :: geçerli sınıf için kullanılan anahtar sözcük ve temelde statik üyelere, yöntemlere ve sabitlere erişmek için kullanılır. Ancak $ bu durumda statik üyeyi, yöntemi ve işlevleri çağıramazsınız.
Sen kullanabilirsiniz öz :: başka sınıf ve erişim statik üyeleri, yöntem ve sabitler anahtar kelime. $ Anahtar kelimesi ne zaman ebeveyn sınıfından ve aynı sınıftan uzatılacağı. Üst sınıftan genişletileceği zaman, başka bir sınıftaki statik olmayan üyelere, yönteme ve işleve erişebilirsiniz.
Aşağıda verilen kod self :: ve $ this anahtar sözcüğünün bir örneğidir . Kodu kopyalayıp kod dosyanıza yapıştırın ve çıktıyı görün.
class cars{
var $doors=4;
static $car_wheel=4;
public function car_features(){
echo $this->doors." Doors <br>";
echo self::$car_wheel." Wheels <br>";
}
}
class spec extends cars{
function car_spec(){
print(self::$car_wheel." Doors <br>");
print($this->doors." Wheels <br>");
}
}
/********Parent class output*********/
$car = new cars;
print_r($car->car_features());
echo "------------------------<br>";
/********Extend class from another class output**********/
$car_spec_show=new spec;
print($car_spec_show->car_spec());