Ne zaman kendini bu $ üzerinde kullanmak için?


Yanıtlar:


1727

Kısa cevap

$thisGeçerli nesneye başvurmak için kullanın . selfGeçerli sınıfa başvurmak için kullanın . Başka bir deyişle, $this->memberstatik olmayan üyeler self::$memberiçin kullanın , statik üyeler için kullanın .

Tam Yanıt

İşte bir örnek , doğru kullanımı $thisve selfsigara 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ı $thisve selfdışı 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 varsa type X, bu nedenle çağırır X::foo(). Nesne varsa, type Yçağırır Y::foo(). Ama self :: foo () X::foo()ile her zaman çağrılır.

Gönderen http://www.phpbuilder.com/board/showthread.php?t=10354489 :

by http://board.phpbuilder.com/member.php?145249-laserlight


330
Bu cevap aşırı derecede basit. Diğer cevaplarda işaret edildiği gibi , geçerli sınıfa başvurmak için selfkapsam çözümleme operatörü ile birlikte kullanılır ::; bu hem statik hem de statik olmayan bağlamlarda yapılabilir. Ayrıca, $thisstatik yöntemleri çağırmak için tamamen yasaldır (ancak referans alanlarına değil).
Artefacto

50
Ayrıca 5.3+ kullanıyorsanız, :: self yerine static :: kullanmayı da düşünün. Aksi halde anlatılmamış baş ağrılarına neden olabilir, neden için aşağıdaki cevabım bakın.
Sqoo

25
-1. Bu cevap yanıltıcıdır, daha fazla bilgi için diğer cevapları okuyun.
Pacerier

6
Aşırı basitleştirilmiş olabilir, ancak kafamı patlatmadan temel düzey sorumu yanıtladı. Daha fazla yardımcı bulduğum daha fazla bilgi aldım, ama şimdilik sadece $ this-> attrib ile sınıf niteliklerime ve self :: constant ile sınıf sabitlerine neden vurduğumu anlamaya çalışıyordum. Bu daha iyi anlamama yardımcı oldu
MydKnight

Ne olmuş $this::?
James

742

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 selfvtable'ı (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()$thisiş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 $thisve çağrılan işlevler içindeki işaretçiye erişebiliyoruz .


3
Bir istisna yerine genel bir kuralla başlarsanız bu cevap daha da iyi olurdu. Bu bir teknik meselesi değil, bir stil meselesi. Bu, self :: ve $ this-> arasındaki farkın gördüğüm en iyi örneğidir, ancak önce bir kavramı çürüterek bunu gizlemek utanç vericidir.
adjwilli

3
@adjwilli: Neden bu kötü stil? OP'nin beklentisi (tezi) önce onaylanmazsa (antitez) ve ardından açıklama sentez olarak verilirse bilinci arttırmıyor mu?
hakre

1
"Güncel sınıf" ı gerçekten sorunlu buluyorum. Bu kelime kombinasyonu hem "bulunduğu sınıf 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.
Jakumi

Ne olmuş $this::?
James

1
@James - kullanmak için iyi bir neden yoktur $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::.
ToolmakerSteve

461

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


6
Sınıf sabitleri ne olacak?
Kevin Bond

53
Msgstr "Ölen :: stat () çağrısı" Kişi öldü "ifadesini görmeyi bekleriz. Hayır. Bu statik bir işlev çağrısıdır, dolayısıyla hiçbir polimorfizm söz konusu değildir.
cquezel

2
PHP'nin tüm kusurlarından biri için bunun çılgınca olduğunu düşünmüyorum. Başka nasıl kodlayıcıların mevcut sınıftaki yöntemleri belirlemelerine izin verirler (onları vtable'a bakmak yerine)? Eğer farklı isimlendirmişlerse (belki de önde gelen alt çizgilerle), bu özelliği isteyen insanlar onu çirkin olduğu için eleştirirdi. Yoksa, aklınıza gelebilecek ne isim olursa olsun, yöntem deliğinin nasıl çalıştığından bile habersiz olan "çılgın" davranışlar için onu eleştiren her zaman kolayca kafası karışmış insanlar olacak gibi görünüyor.
tne

2
Örnek bana kafa karıştırıcı geliyor: getStatusMetodu 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 .
Jānis Elmeris

1
@Sqoo - "self :: KULLANMAYIN, static :: kullanın" yapmak garip bir noktadır - bunlar kasıtlı olarak aynı işlem değildir. Sanırım gerçekten bahsettiğiniz nokta "gerçek :: 'yerine' MyClass :: 'sınıf adını kullanırsanız daha açıktır . Yani, eğer davranış istiyorsanız self::, bunu daha az alabilirsiniz kafa karıştırıcı bir şekilde, belirli bir sınıf adı kullanarak, örn MyClass::.
ToolmakerSteve

248

Gerçekten biz bahsederken bahsettiğinizi anlamak için selfkarşı $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 .

Sınıflar ve Nesneler, Kavramsal

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 $namebir 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 .$bobPersonPerson

Devletin Tanımlanması

Ö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:

  1. Özellikler - Bunları her örneğin içereceği değişkenler olarak düşünün.

    class Foo {
        public $bar = 1;
    }
  2. 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;
    }
  3. Yöntemler - Bunlar, her bir örneğin içereceği (ve örneklerde çalışacağı) işlevlerdir.

    class Foo {
        public function bar() {}
    }
  4. 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() {}
    }
  5. 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.

Durum ve Yöntemler

Bir yöntemin içinde, bir nesnenin örneği $thisdeğ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, $thisdeğ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:

Erişim Durumu

Ş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 Dışından

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->foomantıklı olmadığını belirtmek önemlidir (çünkü Personbir 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.

Örnek / Sınıfın İçinden

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 $thisedecek değil doldurulur. PHP'nin son sürümlerinde (5.3+) bunun bir E_STRICThata 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ı.

Kısayol Anahtar Kelimeleri

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 Foosı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ı staticsınıf adı yerine kullanarak çağırmak, geçerli düzey yerine çağrının nereden geldiğini çözmemize olanak tanır.

Örnekler

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ü selfona 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.

Dikkat Sözü # 1

Ç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 $thisaktarı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, selfveparent ).

Dikkat Sözü # 2

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.

Dikkat Sözü # 3

Genel olarak Geç Statik Bağlama olarak bilinen şeyi kullanmak staticyerine kullanmak istersiniz self. Ama çok kullanmak her zaman" diyerek aynı şey olmadığını not staticyerine selfyerine. 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.

TL / DR

Çok kötü, geri dön ve oku. Çok uzun olabilir, ama bu çok uzun çünkü bu karmaşık bir konu

TL / DR # 2

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).$thisself$this

TL / DR # 3

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.).


1
Dikkat kelimesi 1: statik bir yöntem çağrılırken
Mark Achée

Peki ... $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.
Mark Achée

2
Uzun açıklamayı tamamen okuduktan sonra, tekrar yukarı çıkmak için yukarı kaydırmak için tembel hissettim. Şaka yapıyordum, oy kullandım: D. Teşekkürler bu çok faydalı.
Mr_Green

3
self :: $ property ve self :: property arasındaki fark hakkında net bir açıklama eklemek iyi olurdu; Bence bu oldukça kafa karıştırıcı
Tommaso Barbugli

1
WoC # 1 PHP 7'den beri farklı davranır . Foo::isFoo()Statik olarak adlandırıldığı $thisgibi 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). BarFooFoo::isFoo()
Kontrollfreak

117

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ü thisbir nesne, onu şöyle kullanırsınız:$this->member

Çünkü selfbir nesne değil, otomatik olarak geçerli sınıfa başvuran bir tür temelde, bunu gibi kullanın:self::member


97

$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?

  1. İlk olarak, nesnelere işlev eklemek, işleri düzenli tutmanıza yardımcı olur, böylece onları nerede bulacağınızı bilirsiniz.
  2. İkincisi, adlandırma çatışmalarını önler. Büyük bir projede, iki geliştiricinin getName () işlevleri oluşturması muhtemeldir. Biri bir ClassName1 :: getName () oluşturur ve diğeri ClassName2 :: getName () oluşturursa, hiç sorun değil. Çatışma yok. Statik yöntemler Yay!

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 :)


Mükemmel cevap. Sadece işaret etmek istiyorum, statik bir niteliğe atıfta bulunurken, bir $işaret kullanmanız gerekir . Örneğinself::$templates_path
henrywright

30

Gönderen bu blog yayınında :

  • self şu anki sınıfı ifade eder
  • self statik işlevleri çağırmak ve statik üye değişkenlere başvurmak için kullanılabilir
  • self statik fonksiyonların içinde kullanılabilir
  • self ayrıca vtable'ı atlayarak polimorfik davranışı kapatabilir
  • $this mevcut nesneyi ifade eder
  • $this statik fonksiyonları çağırmak için kullanılabilir
  • $thisstatik üye değişkenleri çağırmak için kullanılmamalıdır. selfBunun yerine kullanın .
  • $this statik fonksiyonlar içinde kullanılamaz

26

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 $thiskullanılabilir olmadığında veya alt sınıfların geçerli yöntemin üzerine yazmasına izin vermek istemediğinizde kullanmalısınız.


22

Sınıf tanımının içinde $thisgeçerli nesneye, selfgeçerli sınıfa atıfta bulunur.

Kullanarak bir sınıf öğesine selfbaş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  

21

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();
?> 


16

Sorunun, sınıfın statik üyesini arayarak çağırabilip çağıramadığına inanıyorum ClassName::staticMember. Soru, kullanma self::classmemberve 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;
    }
}

Cevabınızı "ClassName :: staticMember'i çağırarak sınıfın statik üyesini arayabilip arayamayacağınıza inanmıyorum. Soru, self :: classmember ve $ this-> classmember ile arasındaki farkın ne olduğudur." ve sonra hiçbir fark göstermezsiniz. Aslında, iki seçeneğin aynı şekilde çalıştığı bir örneği gösterirsiniz. -1
Buttle Butkus

Yine de yararlı. Kapsam çözünürlükle ilgiliydi ve bu bölüm php kılavuzunda net değil. Hala yararlı buluyorum
renoirb

2
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
K-Gun

16

self mevcut sınıfı ifade eder (içinde denir),

$thisgeç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


16
  • Nesne işaretçisi $this geçerli nesneyi ifade eder.
  • Sınıf değeri static geçerli nesneyi ifade eder.
  • Sınıf değeri self , tanımlandığı sınıfın aynısıdır.
  • Sınıf değeri 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 staticveya 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)


14

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
İşlem yapmama işlevini 2000 000 kez çağırmak 1s sürer. PHP'yi sevmeliyim.
rr-

Eski PHP iyi. :) Ama bir çağrı = 0.001ms. O kadar mı kötü?
tleb

Bunun (ve benzer şeylerin) ORM'ler gibi şeyleri önbelleklemediğiniz sürece yavaş hissettiklerine ve statik site jeneratörlerinin bir şey olduğuna inanıyorum.
rr-

2
Teorik olarak, 1 / 2e9 s = 0.5 nsbu günlerde yaklaşık 1 işlemci saat döngüsü almalıdır
Buddy

Cevabımı tekrar oku. Dikkatli olun: sınıfı da yaratır . Neden usetbh 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.
tleb

13

Ne zaman selfbirlikte kullanılır ::operatör statik ve statik olmayan bağlamlarda hem yapılabilir akım sınıfına karşılık gelir. $thisnesnenin kendisini ifade eder. Buna ek olarak, $thisstatik yöntemleri çağırmak için tamamen yasaldır (ancak alanlara atıfta bulunmamak).


8

Aynı soruya rastladım ve basit cevap:

  • $this sınıfın bir örneğini gerektirir
  • self:: değil

Kullandığı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 $thisher zaman oluşturulacak nesne üzerinde gerektirir.


7

$thisgeçerli sınıf nesnesini, selfgeç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 staticvethis for none-static members or methods .

çocuk / ebeveyn senaryosunda self / parentda çoğunlukla çocuk ve ebeveyn sınıfı üyelerini ve yöntemlerini tanımlamak için kullanılır.


7

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::.

http://ideone.com/7etRHy

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;


5

selfBir sınıfın yöntemini o sınıfın bir nesnesini / örneğini oluşturmadan çağırmak ve böylece RAM'i kaydetmek istiyorsanız kullanın (bazen bu amaç için kendini kullanın). Başka bir deyişle, aslında statik olarak bir yöntem çağırıyor. thisNesne perspektifi için kullanın .


2

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;
   }
}

1

Php.net göre orada bu bağlamda üç özel anahtar kelimeler: self, parentve static. Sınıf tanımının içinden özelliklere veya yöntemlere erişmek için kullanılırlar.

$thisdiğ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.


-1

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());
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.