Kiedy używać self over $this?

W PHP 5, Jaka jest różnica między używaniem self i $this?

Kiedy każdy jest odpowiedni?

 1802
Author: 7ochem, 2008-09-30

22 answers

Krótka Odpowiedź

Użyj $this, aby odnieść się do bieżącego obiekt. Użyj self, aby odnieść się do obecna Klasa. Innymi słowy, użycie $this->member dla członków niestatycznych, użyj self::$member dla elementów statycznych.

Pełna Odpowiedź

Oto przykład poprawnego użycia $this i self dla niestatycznych i statycznych zmiennych członkowskich:

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

Oto przykład nieprawidłowego użycia $this i self dla pręta niestatycznego i statycznego zmienne:

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

Oto przykład polimorfizmu Z $this dla funkcji członowych:

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

Oto przykład tłumienia zachowania polimorficznego przez użycie self dla funkcji członowych:

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

Idea jest taka, że $this->foo() wywołuje foo() funkcję członka whatever > jest dokładnym typem bieżącego obiektu. Jeśli obiekt jest z type X, to w ten sposób >wywołuje X::foo(). Jeśli obiekt jest z type Y, wywołuje Y::foo(). Ale z > self:: foo(), X::foo() jest zawsze nazywany.

Od http://www.phpbuilder.com/board/showthread.php?t=10354489 :

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

 1527
Author: John Millikin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 06:04:22

Słowo kluczowe self nie odnosi się tylko do 'bieżącej klasy', przynajmniej nie w sposób, który ogranicza cię do statycznych członków. W kontekście elementu niestatycznego, self zapewnia również sposób ominięcia Vtable (zobacz wiki na vtable) dla bieżącego obiektu. Tak jak możesz użyć parent::methodName() do wywołania wersji rodzicielskiej Funkcji, Tak możesz wywołać self::methodName() do wywołania bieżącej implementacji metody klasowej.

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

To wyjdzie:

Witam, Jestem Ludwig geek
Pożegnanie z osobą Ludwiga

sayHello() używa wskaźnika $this, więc vtable jest wywoływany do wywołania Geek::getTitle(). sayGoodbye() używa self::getTitle(), więc vtable nie jest używany, a Person::getTitle() jest wywoływany. W obu przypadkach mamy do czynienia z metodą obiektu instancyjnego i mamy dostęp do wskaźnika $this wewnątrz wywoływanych funkcji.

 712
Author: nbeagle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-10 08:37:04

Nie stosować self::, stosować static::

Jest jeszcze jeden aspekt jaźni::, o którym warto wspomnieć. Irytująco self:: odnosi się do zakresu w punkcie definicji, a nie w punkcie wykonania . Rozważmy tę prostą klasę za pomocą dwóch metod:

class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}

Jeśli zadzwonimy Person::status() zobaczymy "osoba żyje". Teraz zastanów się, co się stanie, gdy stworzymy klasę, która dziedziczy z tego:

class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}

Dzwoniąc Deceased::status() spodziewamy się, że " osoba nie żyje" jednak to, co widzimy, to "Person is alive", ponieważ zakres zawiera oryginalną definicję metody, gdy zostało zdefiniowane wywołanie self::getStatus().

PHP 5.3 ma rozwiązanie. na static:: Operator rozdzielczości implementuje "późne wiązanie statyczne", co jest wymyślnym sposobem na powiedzenie, że jest związane z zakresem wywołanej klasy. Zmień linię w status() na static::getStatus(), a wyniki będą tym, czego oczekujesz. W starszych wersjach PHP będziesz musiał znaleźć kludge, aby to zrobić.

Zobacz PHP Dokumentacja

Aby odpowiedzieć na pytanie nie tak, jak zadano ...

$this-> odnosi się do bieżącego obiektu (instancji klasy), podczas gdy static:: odnosi się do klasy

 430
Author: Sqoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 08:01:45

Aby naprawdę zrozumieć, o czym mówimy, kiedy mówimy o self kontra $this, musimy naprawdę zagłębić się w to, co dzieje się na poziomie koncepcyjnym i praktycznym. Nie czuję, że żadna z odpowiedzi robi to odpowiednio, więc oto moja próba.

Zacznijmy od rozmowy o tym, czym jest Klasa i obiekt .

Klasy I Obiekty, Koncepcyjnie

Więc czym jest a Klasa ? Wielu ludzi definiuje to jako a blueprint or a template for a object. W rzeczywistości możesz przeczytać więcej o klasach w PHP tutaj . I do pewnego stopnia tak naprawdę jest. Spójrzmy na klasę:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

Jak widać, na tej klasie istnieje właściwość o nazwie $name oraz metoda (funkcja) o nazwie sayHello().

Bardzo ważne jest, aby pamiętać, że klasa jest strukturą statyczną. Co oznacza, że Klasa Person, raz zdefiniowana, jest zawsze taka sama gdziekolwiek na to spojrzysz.

Obiekt z drugiej strony jest czymś, co nazywa się instancją klasy. Oznacza to, że bierzemy "schemat" klasy i używamy go do tworzenia dynamicznej kopii. Ta kopia jest teraz specjalnie powiązana ze zmienną, w której jest przechowywana. Dlatego wszelkie zmiany w instancji są lokalne dla tej instancji.

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

Tworzymy nowe instancje klasy używając operatora new.

Dlatego mówimy, że Klasa jest strukturą globalną, a obiekt strukturą lokalną. Nie przejmuj się tą śmieszną składnią, za chwilę się do tego przekonamy.

Inną rzeczą, o której powinniśmy mówić, jest to, że możemy sprawdzić, jeśli instancja jest instanceof konkretną klasą: $bob instanceof Person, która zwraca wartość logiczną, jeśli instancja $bob została utworzona przy użyciu klasy Person, lub potomkiem Person.

Definiowanie Stanu

Więc zagłębimy się trochę w to, co Klasa faktycznie zawiera. Istnieje 5 rodzajów "rzeczy", które klasa zawiera:

  1. Properties - pomyśl o nich jako o zmiennych, które każda instancja będzie zawierać.

    class Foo {
        public $bar = 1;
    }
    
  2. właściwości statyczne - potraktuj je jako zmienne współdzielone na poziomie klasy. Oznacza to, że nigdy nie są one kopiowane przez każdą instancję.

    class Foo {
        public static $bar = 1;
    }
    
  3. metody - są to funkcje, które każda instancja będzie zawierać (i działać na instancje).

    class Foo {
        public function bar() {}
    }
    
  4. metody statyczne - są to funkcje współdzielone przez całą klasę. Działają Nie na instancjach, ale tylko na właściwościach statycznych.

    class Foo {
        public static function bar() {}
    }
    
  5. stałe - stałe rozwiązane klasy. Nie wchodząc tu głębiej, ale dodając dla kompletności:

    class Foo {
        const BAR = 1;
    }
    

Więc zasadniczo, przechowujemy informacje o klasie i kontenerze obiektu używając "podpowiedzi" o statyczne , które określają, czy informacja jest współdzielona (a więc statyczna), czy nie (a więc dynamiczna).

Stan i metody

Wewnątrz metody instancja obiektu jest reprezentowana przez zmienną $this. Obecny stan tego obiektu jest obecny, a mutacja (zmiana) dowolnej właściwości spowoduje zmianę tej instancji (ale nie innych).

Jeśli metoda jest wywoływana statycznie, zmienna $this nie jest zdefiniowana. To dlatego, że jest Żadna instancja powiązana z wywołaniem statycznym.

Interesujące jest to, jak wykonywane są statyczne połączenia. Porozmawiajmy więc o tym, jak uzyskujemy dostęp do stanu: {]}

Stan Dostępu

Więc teraz, kiedy zapisaliśmy ten stan, musimy uzyskać do niego dostęp. Może to być nieco skomplikowane (lub sposób więcej niż bit), więc Podzielmy to na dwa punkty widzenia: spoza instancji / klasy (powiedzmy z normalnego wywołania funkcji lub z globalnego zakresu) i wewnątrz instancji/klasy (z wewnątrz metody na obiekcie).

Poza Instancją / Klasą

Z zewnątrz instancji/klasy, nasze zasady są dość proste i przewidywalne. Mamy dwa operatory i każdy mówi nam natychmiast, czy mamy do czynienia z instancją lub klasą statyczną: {]}

  • -> - object - operator - jest to zawsze używane, gdy uzyskujemy dostęp do instancji.

    $bob = new Person;
    echo $bob->name;
    

    Należy pamiętać, że wywołanie Person->foo nie ma sensu (ponieważ Person jest klasą, nie instancją). Dlatego jest to błąd analizy.

  • :: - scope-resolution-operator - jest to zawsze używane do uzyskania dostępu do właściwości statycznej klasy lub metody.

    echo Foo::bar()
    

    Dodatkowo, możemy wywołać statyczną metodę na obiekcie w ten sam sposób:

    echo $foo::bar()
    

    Jest to niezwykle ważne, aby pamiętać, że kiedy robimy to z zewnątrz, instancja obiektu jest ukryta w metodzie bar(). Co oznacza, że jest to dokładnie tak samo jak bieganie:

    $class = get_class($foo);
    $class::bar();
    

Dlatego $this nie jest zdefiniowana w wywołaniu statycznym.

Z Wnętrza Instancji / Klasy

Trochę się tu zmienia. Te same operatory są używane, ale ich znaczenie staje się znacznie rozmyte.

obiekt-operator -> jest nadal używany do wywoływania stanu instancji obiektu.

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

Wywołanie metody bar() na $foo (instancja Foo) przy użyciu operatora obiektu: $foo->bar() spowoduje powstanie wersji instancji $a.

Więc tego oczekujemy.

Znaczenie :: operatora jednak się zmienia. To zależy od kontekstu wywołania bieżącej funkcji:

  • W kontekście statycznym

    W kontekście statycznym, wszelkie wywołania wykonane za pomocą :: będą również statyczne. Spójrzmy na przykład:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    Wywołanie Foo::bar() wywoła metodę baz() statycznie, a zatem $this wywoła Nie być wypełnione. Warto zauważyć, że w ostatnich wersjach PHP (5.3+) spowoduje to błąd E_STRICT, ponieważ statycznie wywołujemy metody niestatyczne.

  • W kontekście instancji

    W kontekście instancji, wywołania wykonywane za pomocą :: zależą od odbiorcy wywołania (metody, którą wywołujemy). Jeśli metoda jest zdefiniowana jako static, wtedy użyje wywołania statycznego. Jeśli nie, przekieruje instancję informacje.

    Tak więc, patrząc na powyższy kod, wywołanie $foo->bar() zwróci true, ponieważ "statyczne" wywołanie dzieje się wewnątrz kontekstu instancji.

Ma sens? Tak myślałem. To zagmatwane.

Krótkie Słowa Kluczowe

Ponieważ łączenie wszystkiego za pomocą nazw klas jest dość brudne, PHP udostępnia 3 podstawowe" skróty " słowa kluczowe, aby ułatwić rozwiązywanie zakresu.

  • self - odnosi się to do bieżącej nazwy klasy. Więc self::baz() jest taka sama jak Foo::baz() w klasie Foo (Dowolna na niej metoda).

  • parent - odnosi się to do rodzica bieżącej klasy.

  • static - odnosi się to do nazwanej klasy. Dzięki dziedziczeniu klasy potomne mogą nadpisywać metody i właściwości statyczne. Wywołanie ich za pomocą static zamiast nazwy klasy pozwala nam ustalić, skąd pochodzi wywołanie, a nie obecny poziom.

Przykłady

The easiest sposób, aby to zrozumieć, to zacząć patrzeć na kilka przykładów. Wybierzmy klasę:

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

Teraz, mamy tu również do czynienia z dziedziczeniem. Nie jest to dobry model obiektowy, ale przyjrzyjmy się, co się dzieje, gdy bawimy się tym: [83]}

$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

Licznik ID jest więc współdzielony pomiędzy instancjami i dziećmi (ponieważ używamy self, aby uzyskać do niego dostęp. Jeśli użyjemy static, możemy go zastąpić w klasie dziecięcej).

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

Zauważ, że wykonujemy Person::getName() instancja metoda za każdym razem. Ale używamy parent::getName(), aby to zrobić w jednym z przypadków (przypadku dziecka). To właśnie sprawia, że takie podejście jest potężne.

Słowo Ostrożności # 1

Zauważ, że kontekst wywołujący określa, czy dana instancja jest używana. Dlatego:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

Nie jest zawsze prawdą.

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

Teraz jest naprawdę dziwnie tutaj. Wywołujemy inną klasę, ale $this przekazywana do metody Foo::isFoo() jest instancja $bar.

To może powodować różnego rodzaju błędy i pojęciowe WTF-Erie. Sugerowałbym więc unikanie operatora :: Z wewnątrz instancji metod na czegokolwiek poza tymi trzema wirtualnymi" krótkimi " słowami kluczowymi (static, self, i parent).

Słowo Ostrożności # 2

Zauważ, że statyczne metody i właściwości są wspólne dla wszystkich. To czyni je w zasadzie zmiennymi globalnymi. Z tymi samymi problemami, które przychodzą z globalami. Więc byłbym bardzo niezdecydowany aby przechowywać informacje w statycznych metodach / właściwościach, chyba że czujesz się komfortowo, gdy jest to naprawdę globalne.

Słowo Ostrożności # 3

Ogólnie rzecz biorąc, będziesz chciał użyć tego, co jest znane jako późne wiązanie statyczne, używając static zamiast self. Zauważ jednak, że to nie to samo, więc powiedzenie "Zawsze używaj static zamiast self jest naprawdę krótkowzroczne. Zamiast tego zatrzymaj się i pomyśl o wywołaniu, które chcesz wykonać, i pomyśl, czy chcesz, aby klasy dziecięce mogły nadpisać statykę rozwiązane call.

TL/DR

Szkoda, wróć i przeczytaj. Może to być zbyt długie, ale tak długie, ponieważ jest to skomplikowany temat [83]}

TL / DR #2

Ok, w porządku. W skrócie, {[18] } jest używany do odwoływania się do bieżącej nazwy klasy wewnątrz klasy, gdzie jako $this odnosi się do bieżącej instancji obiektu . Zauważ, że self jest skrótem kopiuj / wklej. Możesz bezpiecznie zastąpić go nazwą swojej klasy, i będzie działać dobrze. Ale $this jest dynamicznym zmienna, której nie można określić z wyprzedzeniem (i może nawet nie być twoją klasą).

TL / DR #3

Jeśli użyty jest operator obiektu (->), to zawsze wiesz, że masz do czynienia z instancją. Jeśli operator scope-resolution - jest używany (::), Potrzebujesz więcej informacji o kontekście (czy jesteśmy już w kontekście obiektu? Czy jesteśmy poza obiektem? itp.).

 231
Author: ircmaxell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:26

self (nie $self) odnosi się do typu klasy, gdzie jako $this odnosi się do bieżącej instancji klasy. self jest używany w statycznych funkcjach członkowskich, aby umożliwić dostęp do statycznych zmiennych członkowskich. $this jest używany w niestatycznych funkcjach członkowskich i jest odniesieniem do instancji klasy, na której została wywołana funkcja member.

Ponieważ this jest obiektem, używasz go w następujący sposób: $this->member

Ponieważ self nie jest obiektem, to w zasadzie typ, który automatycznie odnosi się do bieżącej klasy, używasz jej w następujący sposób: self::member

 109
Author: MrZebra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-06 09:49:23

$this-> jest używany do odwoływania się do konkretnej instancji zmiennych klasy (zmiennych członkowskich) lub metod.

Example: 
$derek = new Person();

$ derek jest teraz specyficzną instancją osoby. Każda osoba ma first_name i last_name, ale $derek ma określone first_name i last_name (Derek Martin). Wewnątrz instancji $ derek możemy odnosić się do nich jako $this->first_name i $this - > last_name

ClassName:: jest używane w odniesieniu do tego typu klasy i jej statycznych zmiennych, statycznych metod. Jeśli to pomoże, ty może mentalnie zastąpić słowo "static" słowem "shared". Ponieważ są współdzielone, nie mogą odnosić się do zmiennej $this, która odnosi się do konkretnej instancji (nie współdzielonej). Zmienne statyczne (tzn. statyczne $db_connection) mogą być współdzielone pomiędzy wszystkimi instancjami danego typu obiektu. Na przykład wszystkie obiekty bazy danych mają wspólne połączenie (statyczne $connection).

Przykład Zmiennych Statycznych: Mamy klasę bazy danych z pojedynczą zmienną członkowską: static $num_connections; Włóż to do środka. konstruktor:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

Tak jak obiekty mają konstruktory, mają również destruktory, które są wykonywane, gdy obiekt umiera lub jest wyłączony:

function __destruct()
{
    $num_connections--;
}

Za każdym razem, gdy tworzymy nową instancję, zwiększy to nasz licznik połączeń o jeden. Za każdym razem, gdy zniszczymy lub przestaniemy używać instancji, zmniejszy ona Licznik połączeń o jeden. W ten sposób możemy monitorować liczbę instancji obiektu bazy danych, z którymi mamy w użyciu:

echo DB::num_connections;

Ponieważ $num_connections jest statyczny (współdzielony), będzie odzwierciedlał całkowitą liczbę aktywnych obiektów bazy danych. Być może widziałeś tę technikę używaną do współdzielenia połączeń bazodanowych pomiędzy wszystkimi instancjami klasy bazodanowej. Dzieje się tak, ponieważ tworzenie połączenia z bazą danych zajmuje dużo czasu, więc najlepiej jest utworzyć tylko jedno i udostępnić je (nazywa się to wzorem Singletona).

Metody statyczne (tj. public static View::format_phone_number ($cyfry)) mogą być używane bez pierwszej instancji jednego z tych obiektów (tj. nie odwołuj się wewnętrznie do $this).

Przykład Metody Statycznej:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

Jak widzisz, public static function prettyName nic nie wie o obiekcie. To po prostu praca z parametrami, które przekazujesz, jak normalna funkcja, która nie jest częścią obiektu. Po co więc zawracać sobie głowę, skoro możemy mieć TO NIE jako część obiektu?

  1. Po pierwsze, dołączanie funkcji do obiektów pomaga utrzymać porządek, więc wiesz, gdzie je znaleźć.
  2. drugi, zapobiega konfliktom nazewnictwa. W dużym projekcie prawdopodobnie dwóch programistów utworzy funkcje getName (). Jeśli jeden tworzy ClassName1:: getName (), a drugi tworzy ClassName2:: getName (), to nie ma problemu. Żadnych konfliktów. Yay statyczne metody!

SELF:: Jeśli kodujesz poza obiektem, do którego ma się odnosić statyczna metoda, musisz ją wywołać używając nazwy obiektu View:: format_phone_number ($phone_number); Jeśli kodujesz Wewnątrz obiektu, do którego ma się odnosić statyczna metoda, możesz albo użyć nazwy obiektu View::format_phone_number($PN), albo możesz użyć skrótu self::format_phone_number($PN)

To samo dotyczy zmiennych statycznych: przykład: View:: templates_path versus self:: templates_path

Wewnątrz klasy DB, gdybyśmy odnosili się do statycznej metody jakiegoś innego obiektu, użylibyśmy nazwy obiektu: przykład: Session:: getUsersOnline ();

Ale gdyby Klasa DB chciała odnosić się do własnej zmiennej statycznej, to po prostu powiedziełaby self: przykład: self:: connection;

Mam nadzieję, że to pomoże wyjaśnić sprawę:)

 93
Author: lo_fye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 14:10:47

From this blog post:

  • self odnosi się do bieżącej klasy
  • self może być używany do wywoływania funkcji statycznych i odwoływania się do statycznych zmiennych członkowskich
  • self może być używany wewnątrz funkcji statycznych
  • Może również wyłączyć zachowanie polimorficzne, omijając vtable
  • $this odnosi się do bieżącego obiektu
  • $this może być używany do wywoływania funkcji statycznych
  • $this nie powinien być stosowany do wywołanie statycznych zmiennych członkowskich. Zamiast tego użyj self.
  • $this nie może być używany wewnątrz funkcji statycznych
 27
Author: okconfused,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-24 15:46:59

W PHP, używasz słowa kluczowego self, aby uzyskać dostęp do statycznych właściwości i metod.

Problem polega na tym, że możesz zamienić $this->method() na self::method() w dowolnym miejscu, niezależnie od tego, czy method() jest zadeklarowana jako statyczna, czy nie. Więc którego z nich powinieneś użyć?

Rozważ ten kod:

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

W tym przykładzie, self::who() zawsze wyświetli "rodzic", podczas gdy $this->who() będzie zależeć od klasy obiektu.

Teraz widzimy, że jaźń odnosi się do klasy, w której jest wywoływana, podczas gdy $this odnosi się do Klasa bieżącego obiektu .

Tak więc, powinieneś używać self tylko wtedy, gdy $this nie jest dostępna, lub gdy nie chcesz, aby klasy potomne nadpisywały bieżącą metodę.

 23
Author: ramin rostami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-28 17:06:03

Wewnątrz definicji klasy, $this odnosi się do bieżącego obiektu, podczas gdy self odnosi się do bieżącej klasy.

Konieczne jest odwoływanie się do elementu klasy za pomocą self i odwoływanie się do elementu obiektu za pomocą $this.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
 19
Author: Tarun Singhal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-14 12:57:19

Oto przykład poprawnego użycia $this I self dla niestatycznych oraz statyczne zmienne członkowskie:

<?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();
?> 
 17
Author: Mohit Bumb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 11:26:22

Zgodnie z http://www.php.net/manual/en/language.oop5.static.php nie ma $self. Istnieje tylko $this, do odwoływania się do bieżącej instancji klasy (obiektu), oraz self, które mogą być używane do odwoływania się do statycznych członków klasy. Tutaj wchodzi w grę Różnica między instancją obiektu a klasą.

 16
Author: cruizer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 14:10:30

Ponieważ nikt tutaj nie mówił o występach, oto mały benchmark, który zrobiłem (5.6):

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

Oto wyniki 2 000 000 biegów, a oto kod, którego użyłem:

<?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();
 12
Author: tleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 05:04:55

self odwołuje się do bieżącej klasy (w której jest wywoływana),

$this odnosi się do bieżącego obiektu. Możesz używać statyki zamiast jaźni. Zobacz przykład:

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

Wyjście: rodzic dziecko

 12
Author: Kabir Hossain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 14:12:42

Wydaje mi się, że pytaniem nie było, czy można wywołać statycznego członka klasy przez wywołanie ClassName::staticMember. Pytanie brzmiało, jaka jest różnica między używaniem self::classmember i $this->classmember.

Na przykład, oba poniższe przykłady działają bez żadnych błędów, niezależnie od tego, czy używasz self:: Czy $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;
    }
}
 11
Author: Akintunde-Rotimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 14:11:20
  • Wskaźnik obiektu $this do odnosi się do bieżącego obiektu.
  • wartość klasy "static" odnosi się do bieżącego obiektu.
  • wartość klasy "self" odnosi się do dokładnej klasy, w której została zdefiniowana.
  • wartość klasy "parent" odnosi się do rodzica dokładnej klasy, w której została zdefiniowana.

Zobacz poniższy przykład, który pokazuje przeciążenie.

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

Przez większość czasu chcesz odwoływać się do bieżącej klasy, dlatego używasz static lub $this. Jednakże, są chwile, kiedy potrzebujesz self ponieważ chcesz oryginalną klasę niezależnie od tego, co ją rozszerza. (Bardzo, bardzo rzadko)

 10
Author: Xeoncross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-22 15:30:00

Gdy self jest używane z operatorem ::, odnosi się do bieżącej klasy, która może być wykonywana zarówno w statycznych, jak i niestatycznych kontekstach. $this odnosi się do samego obiektu. Ponadto jest całkowicie legalne używanie $this do wywoływania metod statycznych(ale nie odwoływania się do pól).

 10
Author: mrDjouk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-22 15:34:05

$this odnosi się do bieżącego obiektu klasy, self odnosi się do bieżącej klasy (Nie obiektu). Klasa jest schematem obiektu. Więc definiujesz klasę, ale konstruujesz obiekty.

Innymi słowy, użyj self for static i this for none-static members or methods.

Również w scenariuszu child / parent self / parent jest najczęściej używany do identyfikowania członków klasy child I parent oraz metod.

 5
Author: Rakesh Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-15 06:36:28

Dodatkowo od {[1] } nie został jeszcze omówiony.

Tylko w celach informacyjnych, począwszy od PHP 5.3, kiedy mamy do czynienia z instancyjnymi obiektami, aby uzyskać bieżącą wartość zakresu, w przeciwieństwie do static::, można alternatywnie użyć $this:: w ten sposób.

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

Używanie powyższego kodu nie jest powszechną lub zalecaną praktyką, ale służy po prostu zilustrowaniu jego użycia i ma działać bardziej jako " Czy wiesz?"w nawiązaniu do oryginału pytanie z plakatu.

Reprezentuje również użycie $object::CONSTANT na przykład echo $foo::NAME; W przeciwieństwie do $this::NAME;

 5
Author: fyrye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 17:02:26

Użyj self jeśli chcesz wywołać metodę klasy bez tworzenia obiektu / instancji tej klasy, zapisując w ten sposób RAM (czasami użyj self do tego celu). Innymi słowy, jest to w rzeczywistości wywołanie metody statycznie. Użyj this dla perspektywy obiektu.

 4
Author: minhajul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 14:12:05

Przypadek 1: Użycie self może być użyte dla stałych klasy

 class classA { 
     const FIXED_NUMBER = 4; 
     self::POUNDS_TO_KILOGRAMS
}

Jeśli chcesz wywołać go poza klasą, użyj classA::POUNDS_TO_KILOGRAMS, aby uzyskać dostęp do stałych

Przypadek 2: dla właściwości statycznych

class classC {
     public function __construct() { 
     self::$_counter++; $this->num = self::$_counter;
   }
}
 1
Author: li bing zhao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-02 21:14:00

Natknąłem się na to samo pytanie i prosta odpowiedź brzmi:

  • $this wymaga instancji klasy
  • self:: doesn ' t

Kiedykolwiek używasz metod statycznych lub atrybutów statycznych i chcesz je wywołać bez posiadania obiektu klasy, musisz użyć self:: aby je wywołać, ponieważ $this zawsze wymaga utworzenia obiektu.

 1
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-19 15:23:49

Według php.net w tym kontekście istnieją trzy specjalne słowa kluczowe: self, parent i static. Są one używane do uzyskiwania dostępu do Właściwości lub metod z poziomu definicji klasy.

$this, z drugiej strony, jest używany do wywołania instancji i metod dowolnej klasy, o ile ta klasa jest dostępna.

 0
Author: Fil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-07 12:26:21