W PHP 5 jaka jest różnica między używaniem self
a $this
?
Kiedy każdy jest odpowiedni?
W PHP 5 jaka jest różnica między używaniem self
a $this
?
Kiedy każdy jest odpowiedni?
Odpowiedzi:
Użyj,
$this
aby odnieść się do bieżącego obiektu. Użyj,self
aby odnieść się do bieżącej klasy. Innymi słowy, użyj$this->member
dla elementów niestatycznych, użyjself::$member
dla elementów statycznych.
Oto przykład poprawnego użycia $this
i self
dla niestatycznych i statycznych zmiennych składowych:
<?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 niestatycznych i statycznych zmiennych składowych:
<?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 ze $this
dla funkcji składowych:
<?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 przy użyciu self
funkcji składowych:
<?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();
?>
Chodzi o to, że
$this->foo()
wywołujefoo()
funkcję członka niezależnie od dokładnego typu bieżącego obiektu. Jeśli obiekt jesttype X
, to wywołujeX::foo()
. Jeśli obiekt jesttype Y
, wywołujeY::foo()
. Ale z self :: foo ()X::foo()
jest zawsze wywoływane.
Od http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Przez http://board.phpbuilder.com/member.php?145249-laserlight
self
jest używany z operatorem rozdzielczości zakresu ::
w odniesieniu do bieżącej klasy; można to zrobić zarówno w kontekście statycznym, jak i niestatycznym. Ponadto jest całkowicie legalne, aby $this
wywoływać metody statyczne (ale nie do pól referencyjnych).
$this::
?
Słowo kluczowe self NIE odnosi się tylko do „bieżącej klasy”, a przynajmniej nie w sposób, który ogranicza cię do elementów statycznych. W kontekście elementu niestatycznego self
zapewnia również sposób na ominięcie vtable ( patrz wiki na vtable ) dla bieżącego obiektu. Tak jak możesz użyć parent::methodName()
do wywołania rodzicielskiej wersji funkcji, możesz self::methodName()
także wywołać bieżącą implementację klasy metody.
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();
Spowoduje to:
Cześć, jestem Ludwig maniakiem
Żegnaj Ludwig od osoby
sayHello()
używa $this
wskaźnika, więc vtable jest wywoływany do wywołania Geek::getTitle()
.
sayGoodbye()
używa self::getTitle()
, więc vtable nie jest używane i Person::getTitle()
jest wywoływane. W obu przypadkach mamy do czynienia z metodą instancji obiektu i mamy dostęp do $this
wskaźnika w ramach wywoływanych funkcji.
self
znajduje” / „definicję klasy, jest ona dosłowną częścią”, jak również „klasę obiektu” (która w rzeczywistości byłaby static
).
$this::
?
$this::
; wszystkie możliwe przypadki są już objęte częściej stosowanymi składniami. W zależności od tego, co masz na myśli, stosowanie $this->
, self::
lub static::
.
NIE UŻYWAJ self::
, używajstatic::
Jest jeszcze jeden aspekt self ::, o którym warto wspomnieć. Irytująco self::
odnosi się do zakresu w punkcie definicji, a nie w miejscu wykonania . Rozważ 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”. Zastanówmy się teraz, co się stanie, gdy stworzymy klasę, która odziedziczy po tym:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Wywołanie Deceased::status()
oczekiwałoby, że zobaczymy „Osoba nie żyje”, ale widzimy, że „Osoba żyje”, ponieważ zakres zawiera oryginalną definicję metody, gdy zdefiniowano wywołanie self::getStatus()
.
PHP 5.3 ma rozwiązanie. te static::
narzędzia operator rozdzielczości „wiązanie późne statyczne”, który to sposób fantazyjny mówić, że to wiąże się z zakresem klasy nazwie. Zmień linię status()
na, static::getStatus()
a wyniki będą zgodne z oczekiwaniami. W starszych wersjach PHP musisz znaleźć kludge, aby to zrobić.
Zobacz dokumentację PHP
Aby odpowiedzieć na pytanie, które nie zostało zadane ...
$this->
odnosi się do bieżącego obiektu (instancji klasy), podczas gdy static::
odnosi się do klasy
getStatus
metodę jako taką, którą wywołałbym dla instancji klasy, a nie dla klasy.
self::
, możesz uzyskać to mniej myląco, używając konkretnej nazwy klasy, np MyClass::
.
Aby naprawdę zrozumieć, o czym mówimy, gdy mówimy o self
kontra $this
, musimy naprawdę zagłębić się w to, co dzieje się na poziomie koncepcyjnym i praktycznym. Nie wydaje mi się, żeby żadna z odpowiedzi zrobiła to odpowiednio, więc oto moja próba.
Zacznijmy od rozmowy o tym, czym jest klasa i obiekt .
Więc, co jest klasa ? Wiele osób definiuje go jako plan lub szablon obiektu. 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ć, w tej klasie jest wywołana właściwość $name
i wywołana metoda (funkcja) sayHello()
.
To bardzo ważne, aby pamiętać, że klasa jest strukturą statyczną. Co oznacza, że Person
raz zdefiniowana klasa jest zawsze taka sama wszędzie tam, gdzie na nią spojrzysz.
Natomiast obiekt to tak zwana instancja klasy. Oznacza to, że bierzemy „plan” klasy i używamy go do wykonania dynamicznej kopii. Ta kopia jest teraz ściśle 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 wystąpienia klasy za pomocą new
operatora.
Dlatego mówimy, że Klasa jest strukturą globalną, a Obiekt jest strukturą lokalną. Nie martw się tą zabawną ->
składnią, zajmiemy się nią za chwilę.
Kolejną rzeczą, o której powinniśmy porozmawiać, jest to, że możemy sprawdzić, czy instancja jest instanceof
określoną klasą: $bob instanceof Person
która zwraca wartość logiczną, jeśli $bob
instancja została wykonana przy użyciu Person
klasy, lub elementu potomnego Person
.
Zobaczmy więc, co tak naprawdę zawiera klasa. Istnieje 5 rodzajów „rzeczy”, które zawiera klasa:
Właściwości - traktuj je jako zmienne, które będzie zawierać każda instancja.
class Foo {
public $bar = 1;
}
Właściwości statyczne - Pomyśl o nich jak o zmiennych, które są współużytkowane na poziomie klasy. Oznacza to, że nigdy nie są kopiowane przez każdą instancję.
class Foo {
public static $bar = 1;
}
Metody - są to funkcje, które każda instancja będzie zawierała (i działała na instancjach).
class Foo {
public function bar() {}
}
Metody statyczne - są to funkcje wspólne dla całej klasy. Oni nie działają w przypadkach, lecz tylko na właściwości statycznych.
class Foo {
public static function bar() {}
}
Stałe - stałe klasowe. Nie wchodzę tutaj głębiej, ale dodajemy dla kompletności:
class Foo {
const BAR = 1;
}
Zasadniczo przechowujemy informacje na temat kontenera klasy i obiektu za pomocą „wskazówek” o statyce, które określają, czy informacja jest współdzielona (a więc statyczna), czy nie (a więc dynamiczna).
Wewnątrz metody instancja obiektu jest reprezentowana przez $this
zmienną. Obecny stan tego obiektu już istnieje, a mutacja (zmiana) dowolnej właściwości spowoduje zmianę tego wystąpienia (ale nie innych).
Jeśli metoda jest wywoływana statycznie, $this
zmienna nie jest zdefiniowana . Jest tak, ponieważ nie ma instancji powiązanej z wywołaniem statycznym.
Interesującą rzeczą jest tutaj sposób wykonywania połączeń statycznych. Porozmawiajmy więc o tym, w jaki sposób uzyskujemy dostęp do stanu:
Teraz, kiedy już zapisaliśmy ten stan, musimy uzyskać do niego dostęp. Może to być nieco trudne (lub o wiele więcej), dlatego podzielmy to na dwa punkty widzenia: spoza instancji / klasy (powiedzmy z normalnego wywołania funkcji lub z zakresu globalnego) i wewnątrz instancji / class (z metody na obiekcie).
Z zewnątrz instancji / klasy nasze zasady są dość proste i przewidywalne. Mamy dwóch operatorów i każdy z nas natychmiast informuje nas, jeśli mamy do czynienia z instancją lub statyczną klasą:
->
- operator obiektu - jest zawsze używany, gdy uzyskujemy dostęp do instancji.
$bob = new Person;
echo $bob->name;
Ważne jest, aby pamiętać, że wywoływanie Person->foo
nie ma sensu (ponieważ Person
jest klasą, a nie instancją). Dlatego jest to błąd analizy.
::
- operator-rozdzielczości-zakresu - zawsze służy do uzyskania dostępu do właściwości lub metody statycznej klasy.
echo Foo::bar()
Dodatkowo możemy wywołać metodę statyczną na obiekcie w ten sam sposób:
echo $foo::bar()
Jest to niezwykle ważne, aby pamiętać, że gdy robimy to z zewnątrz , instancja obiektu jest ukryte przed bar()
metody. Oznacza to, że jest to dokładnie to samo, co bieganie:
$class = get_class($foo);
$class::bar();
Dlatego $this
nie jest zdefiniowany w wywołaniu statycznym.
Tutaj coś się trochę zmienia. Używane są te same operatory, ale ich znaczenie staje się znacznie rozmyte.
Operator obiektu ->
jest nadal używany do wywoływania stanu instancji obiektu.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Wywołanie bar()
metody $foo
(instancja Foo
) przy użyciu operatora obiektu: $foo->bar()
spowoduje utworzenie wersji instancji $a
.
Tak właśnie się spodziewamy.
Znaczenie ::
operatora zmienia się. Zależy to od kontekstu wywołania bieżącej funkcji:
W kontekście statycznym
W kontekście statycznym wszelkie wywołania wykonane przy użyciu ::
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 baz()
metodę statycznie, a więc $this
będzie nie być wypełniane. Warto zauważyć, że w najnowszych wersjach PHP (5.3+) spowoduje to E_STRICT
błąd, ponieważ statycznie nazywamy metody niestatyczne.
W kontekście instancji
Z drugiej strony, w kontekście wystąpienia, wywołania wykonane ::
zależą od odbiorcy wywołania (metody, którą wywołujemy). Jeśli metoda jest zdefiniowana jako static
, wówczas użyje wywołania statycznego. Jeśli nie, prześle informacje o instancji.
Tak więc, patrząc na powyższy kod, wywołanie $foo->bar()
powróci true
, ponieważ wywołanie „statyczne” odbywa się w kontekście instancji.
Ma sens? Tak nie myślałem. To jest mylące.
Ponieważ wiązanie wszystkiego za pomocą nazw klas jest raczej brudne, PHP udostępnia 3 podstawowe słowa kluczowe „skrótowe”, aby ułatwić rozwiązywanie zakresu.
self
- Odnosi się do bieżącej nazwy klasy. Tak self::baz()
samo jest Foo::baz()
w Foo
klasie (dowolna metoda).
parent
- Odnosi się do rodzica bieżącej klasy.
static
- Odnosi się to do wywoływanej klasy. Dzięki dziedziczeniu klasy potomne mogą zastępować metody i właściwości statyczne. Wywołanie ich przy użyciu static
zamiast nazwy klasy pozwala nam ustalić, skąd pochodzi połączenie, a nie na bieżącym poziomie.
Najłatwiej to zrozumieć, zaczynając od kilku 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 przyglądamy się również dziedziczeniu. Zignoruj przez chwilę, że jest to zły model obiektowy, ale spójrzmy na to, co się stanie, gdy będziemy się z tym bawić:
$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 identyfikatorów jest więc współużytkowany przez obie instancje i dzieci (ponieważ korzystamy self
z niego, aby uzyskać do niego dostęp. Gdybyśmy korzystali static
, moglibyśmy zastąpić go w klasie potomnej).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Pamiętaj, że za każdym razem wykonujemy metodę Person::getName()
instancji . Ale używamy parent::getName()
do tego w jednym z przypadków (przypadek podrzędny). To sprawia, że to podejście jest potężne.
Zauważ, że kontekst wywołania określa, czy instancja jest używana. W związku z tym:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Nie zawsze jest to prawda.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Teraz jest tu naprawdę dziwnie. Wzywamy inną klasę, ale metoda $this
przekazywana do Foo::isFoo()
metody jest instancją klasy $bar
.
Może to powodować różnego rodzaju błędy i koncepcyjne WTF. Więc ja bardzo sugerują unikanie ::
operatora od wewnątrz metody instancji na wszystko z wyjątkiem tych trzech wirtualnych „short-cut” (słowa kluczowe static
, self
i parent
).
Pamiętaj, że wszystkie metody i właściwości statyczne są wspólne. To czyni je zasadniczo zmiennymi globalnymi. Z tymi samymi problemami, które występują w globalsach. Byłbym więc bardzo niezdecydowany, aby przechowywać informacje w statycznych metodach / właściwościach, chyba że czujesz się swobodnie, ponieważ jest to prawdziwie globalne.
Ogólnie rzecz biorąc, będziesz chciał użyć tak zwanego późnego wiązania statycznego, używając static
zamiast self
. Pamiętaj jednak, że to nie to samo, dlatego powiedzenie „zawsze używaj static
zamiast zamiast self
jest naprawdę krótkowzroczne. Zamiast tego zatrzymaj się i pomyśl o połączeniu, które chcesz wykonać, i pomyśl, czy chcesz, aby klasy potomne mogły zastąpić to rozwiązanie statyczne połączenie.
Szkoda, wróć i przeczytaj. To może być za długie, ale tak długo, ponieważ jest to złożony temat
Ok dobrze. W skrócie, self
służy do odwołania do bieżącej nazwy klasy w klasie, gdzie $this
odnosi się do bieżącej instancji obiektu . Pamiętaj, że self
jest to skrót do kopiowania / wklejania. Możesz go bezpiecznie zastąpić nazwą klasy i będzie dobrze działać. Ale $this
jest zmienną dynamiczną, której nie można ustalić z wyprzedzeniem (i może nawet nie być twoją klasą).
Jeśli używany jest operator obiektu ( ->
), zawsze wiesz, że masz do czynienia z instancją. Jeśli używany jest operator rozpoznawania zakresu ( ::
), potrzebujesz więcej informacji o kontekście (czy już jesteśmy w kontekście obiektowym? Czy jesteśmy poza obiektem? Itp.).
$this
nie zostanie zdefiniowany, jeśli będziesz przestrzegać „ścisłych standardów” i nie wywołasz metod statycznie, które nie są zdefiniowane jako statyczne. Widzę wynik, który wyjaśniłeś tutaj: 3v4l.org/WeHVM Zgoda, naprawdę dziwne.
Foo::isFoo()
to się nazywa statycznie, $this
nie zostanie zdefiniowane. To moim zdaniem bardziej intuicyjne zachowanie. - Podaje się inny wynik, jeśli Bar
miałby zostać przedłużony Foo
. Wtedy wywołanie Foo::isFoo()
byłoby w rzeczywistości w kontekście instancji (nie jest specyficzne dla PHP7).
self
(nie $ self) odnosi się do typu klasy, gdzie $this
odnosi się do bieżącej instancji klasy. self
jest przeznaczony do użycia w statycznych funkcjach członka, aby umożliwić ci dostęp do statycznych zmiennych członka. $this
jest używany w niestatycznych funkcjach składowych i jest odwołaniem do instancji klasy, w której wywołano funkcję składową.
Ponieważ this
jest to obiekt, używasz go w następujący sposób:$this->member
Ponieważ self
nie jest obiektem, jest to po prostu typ, który automatycznie odnosi się do bieżącej klasy, używasz go w następujący sposób:self::member
$this->
jest używany w odniesieniu do określonego wystąpienia zmiennych klasy (zmiennych składowych) lub metod.
Example:
$derek = new Person();
$ derek jest teraz specyficzną instancją Osoby. Każda osoba ma imię i nazwisko, ale $ derek ma określone imię i nazwisko (Derek Martin). Wewnątrz instancji $ derek możemy nazywać ją $ this-> first_name i $ this-> last_name
KlasaNazwa :: jest używana w odniesieniu do tego typu klasy i jej zmiennych statycznych, metod statycznych. Jeśli to pomoże, możesz mentalnie zastąpić słowo „statyczny” słowem „udostępniony”. Ponieważ są udostępnione, nie mogą odnosić się do $ this, który odnosi się do konkretnej instancji (nieudostępnionej). Zmienne statyczne (tj. Static $ db_connection) mogą być współużytkowane przez wszystkie instancje typu obiektu. Na przykład wszystkie obiekty bazy danych dzielą jedno połączenie (połączenie statyczne $).
Zmienne statyczne Przykład: Udawaj, że mamy klasę bazy danych z jedną zmienną składową: static $ num_connections; Teraz wstaw to do konstruktora:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Podobnie jak obiekty mają konstruktory, mają także destruktory, które są wykonywane, gdy obiekt umiera lub jest rozbrojony:
function __destruct()
{
$num_connections--;
}
Za każdym razem, gdy tworzymy nową instancję, zwiększy ona licznik połączeń o jeden. Za każdym razem, gdy niszczymy lub przestajemy używać instancji, zmniejsza ona licznik połączeń o jeden. W ten sposób możemy monitorować liczbę instancji obiektu bazy danych, którego używamy z:
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ń z bazą danych między wszystkimi instancjami klasy bazy danych. Dzieje się tak, ponieważ tworzenie połączenia z bazą danych zajmuje dużo czasu, dlatego najlepiej utworzyć tylko jedno i udostępnić je (nazywa się to Wzorem Singletona).
Metody statyczne (tj. Publiczny widok statyczny :: numer_format_pliku (cyfry $)) mogą być używane BEZ pierwszej instancji jednego z tych obiektów (tzn. Nie odnoszą 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 widać, publiczna funkcja statyczna prettyName nie wie nic o obiekcie. Po prostu działa z parametrami, które przekazujesz, jak normalna funkcja, która nie jest częścią obiektu. Po co więc zawracać sobie głowę, skoro nie moglibyśmy mieć go jako przedmiotu?
SELF :: Jeśli kodujesz poza obiektem, który ma metodę statyczną, do której chcesz się odwoływać, musisz wywołać go przy użyciu nazwy obiektu View :: format_phone_number ($ phone_number); Jeśli kodowanie wewnątrz obiektu, który ma metodę statyczną chcesz zwrócić, można też korzystać z obiektu nazwa widoku :: format_phone_number ($ PN) lub można użyć self :: $ format_phone_number (PN) skrót
To samo dotyczy zmiennych statycznych: Przykład: View :: templates_path vs. self :: templates_path
Wewnątrz klasy DB, gdybyśmy odwoływali się do metody statycznej jakiegoś innego obiektu, użylibyśmy nazwy obiektu: Przykład: Session :: getUsersOnline ();
Ale gdyby klasa DB chciała odwoływać się do własnej zmiennej statycznej, powiedziałaby po prostu self: Przykład: self :: connection;
Mam nadzieję, że pomoże to wyjaśnić :)
$
znaku. Na przykładself::$templates_path
self
odnosi się do bieżącej klasyself
może być używany do wywoływania funkcji statycznych i odwoływania się do statycznych zmiennych składowychself
może być używany wewnątrz funkcji statycznychself
może także wyłączyć zachowanie polimorficzne, omijając tabelę vt$this
odnosi się do bieżącego obiektu$this
może być używany do wywoływania funkcji statycznych$this
nie należy używać do wywoływania statycznych zmiennych składowych. Użyjself
zamiast tego.$this
nie może być stosowany w funkcjach statycznych
W PHP używasz słowa kluczowego self, aby uzyskać dostęp do właściwości i metod statycznych.
Problemem jest to, że można zastąpić $this->method()
z self::method()
dowolnego miejsca, niezależnie od tego czy method()
jest static czy nie. Którego 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”, a $this->who()
będzie zależeć od tego, jaką klasę ma obiekt.
Teraz widzimy, że self odnosi się do klasy, w której jest wywoływane, natomiast $this
odnosi się do klasy bieżącego obiektu .
Dlatego powinieneś używać self tylko wtedy, gdy $this
nie jest ono dostępne lub gdy nie chcesz pozwolić klasom potomnym na zastąpienie bieżącej metody.
Wewnątrz definicji klasy $this
odnosi się do bieżącego obiektu, a self
odnosi się do bieżącej klasy.
Konieczne jest odwołanie się do elementu klasy za pomocą self
i odniesienia do elementu obiektu za pomocą $this
.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Oto przykład poprawnego użycia $ this i self dla niestatycznych i statycznych zmiennych składowych:
<?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();
?>
Według http://www.php.net/manual/en/language.oop5.static.php nie ma $self
. Istnieje tylko $this
odniesienie do bieżącej instancji klasy (obiektu) i self, które może służyć do odwoływania się do statycznych elementów klasy. W grę wchodzi tutaj różnica między instancją obiektu a klasą.
Uważam, że nie było pytania, czy można wywołać statycznego członka klasy, dzwoniąc ClassName::staticMember
. Pytanie brzmiało, jaka jest różnica między używaniem self::classmember
a$this->classmember
.
Na przykład oba poniższe przykłady działają bezbłędnie, 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;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
odnosi się do bieżącej klasy (w której się nazywa),
$this
odnosi się do bieżącego obiektu. Możesz użyć statycznego zamiast siebie. 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: dziecko nadrzędne
$this
odnosi się do bieżącego obiektu.static
odnosi się do bieżącego obiektu.self
odnosi się do dokładnej klasy, w której została zdefiniowana.parent
odnosi się do rodzica dokładnej klasy, w której została zdefiniowana.Zobacz następujący 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
. Są jednak chwile, kiedy potrzebujesz, self
ponieważ chcesz oryginalnej klasy bez względu na to, co ją rozszerza. (Bardzo, bardzo rzadko)
Ponieważ nikt tutaj nie mówił o występach, oto mały test, który zrobiłem (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
To są wyniki dla 2 000 000 przebiegó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();
1 / 2e9 s = 0.5 ns
tych dniach
use
użyłem słowa kluczowego tbh, ale nie mam już PHP, aby powtórzyć test porównawczy, i nie mam ochoty go ponownie instalować.
Natrafiłem na to samo pytanie, a prosta odpowiedź brzmi:
$this
wymaga wystąpienia klasyself::
nieIlekroć używasz metod statycznych lub atrybutów statycznych i chcesz je wywoływać bez tworzenia instancji obiektu klasy, musisz użyć ich self:
do wywołania, ponieważ $this
zawsze wymaga utworzenia obiektu.
$this
odnosi się do bieżącego obiektu klasy, self
odnosi się do bieżącej klasy (nie obiektu). Klasa jest planem 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 podrzędnym / nadrzędnym self / parent
stosuje się głównie do identyfikacji członków i metod klas podrzędnych i nadrzędnych.
Ponadto, ponieważ $this::
nie został jeszcze omówiony.
Wyłącznie w celach informacyjnych, począwszy od PHP 5.3 w przypadku obiektów utworzonych w celu uzyskania bieżącej wartości zakresu, w przeciwieństwie do używania static::
, można alternatywnie używać w ten $this::
sposób.
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życie powyższego kodu nie jest powszechną ani zalecaną praktyką, ale służy jedynie zilustrowaniu jego użycia i ma charakter bardziej przypominający „Czy wiesz?” w nawiązaniu do pytania oryginalnego plakatu.
Reprezentuje również użycie $object::CONSTANT
npecho $foo::NAME;
. W przeciwieństwie do$this::NAME;
Użyj, self
jeśli chcesz wywołać metodę klasy bez tworzenia obiektu / instancji tej klasy, oszczędzając w ten sposób pamięć RAM (czasami do tego celu używaj self). Innymi słowy, faktycznie wywołuje metodę statycznie. Użyj this
do perspektywy obiektu.
Przypadek 1: Użyj self
może być użyte dla stałych klas
klasa klasa A { 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
klasa klasa C { funkcja publiczna __construct () { self :: $ _ counter ++; $ this-> num = self :: $ _ counter; } }
słowo kluczowe :: :: używane dla bieżącej klasy i zasadniczo służy do uzyskiwania dostępu do elementów statycznych, metod i stałych. Ale w przypadku $ nie można wywołać statycznego elementu, metody i funkcji.
Możesz użyć słowa kluczowego self :: w innej klasie i uzyskać dostęp do elementów statycznych, metody i stałych. Kiedy będzie rozszerzany z klasy nadrzędnej i tak samo w przypadku $ tego słowa kluczowego. Możesz uzyskać dostęp do niestatycznych elementów, metody i funkcji w innej klasie, gdy będzie ona rozszerzana z klasy nadrzędnej.
Podany poniżej kod jest przykładem słowa kluczowego self :: i $ . Po prostu skopiuj i wklej kod do pliku kodu i zobacz wynik.
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());