Zapytam, jaka jest różnica między: cd. A; $ this-> A and self :: A
timmz
Odpowiedzi:
1727
Krótka odpowiedź
Użyj, $thisaby odnieść się do bieżącego obiektu. Użyj, selfaby odnieść się do bieżącej klasy. Innymi słowy, użyj
$this->memberdla elementów niestatycznych, użyj self::$memberdla elementów statycznych.
Pełna odpowiedź
Oto przykład poprawnego użycia $thisi selfdla niestatycznych i statycznych zmiennych składowych:
Oto przykład polimorfizmu ze $thisdla funkcji składowych:
<?phpclass 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 selffunkcji 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łuje foo()funkcję członka niezależnie od dokładnego typu bieżącego obiektu. Jeśli obiekt jest type X, to wywołuje X::foo(). Jeśli obiekt jest type Y, wywołuje Y::foo(). Ale z self :: foo () X::foo()jest zawsze wywoływane.
Ta odpowiedź jest zbyt uproszczona. Jak wskazano w innych odpowiedziach, selfjest 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 $thiswywoływać metody statyczne (ale nie do pól referencyjnych).
Artefacto,
50
Rozważ także użycie static :: zamiast :: self, jeśli korzystasz z wersji 5.3+. W przeciwnym razie może to powodować niezliczone bóle głowy, zobacz moją odpowiedź poniżej, dlaczego.
Sqoo,
25
-1. Ta odpowiedź jest myląca, przeczytaj pozostałe odpowiedzi, aby uzyskać więcej informacji.
Pacerier
6
Może to być nadmiernie uproszczone, ale odpowiadało na moje podstawowe pytanie, nie powodując wybuchu mojej głowy. Dostałem trochę więcej informacji, które uważałem za pomocne w dalszej części, ale na razie próbowałem po prostu dowiedzieć się, dlaczego trafiłem w moje atrybuty klasy za pomocą $ this-> attrib, a stałe klasy za pomocą self :: constant. Pomogło mi to zrozumieć
MydKnight,
Co $this::?
James
742
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 selfzapewnia 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.
Cześć, jestem Ludwig maniakiem
Żegnaj Ludwig od osoby
sayHello()używa $thiswskaź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 $thiswskaźnika w ramach wywoływanych funkcji.
Ta odpowiedź byłaby jeszcze lepsza, gdybyś zaczął od ogólnej reguły zamiast wyjątku. To kwestia stylu, a nie wiedzy technicznej. To najlepszy przykład, jaki kiedykolwiek widziałem na temat różnicy między self :: a $ this->, ale wstydem jest ukrywać to, najpierw obalając pojęcie.
adjwilli
3
@adjwilli: Dlaczego ten zły styl? Czy to nie podnosi świadomości, że oczekiwanie (teza) PO jest najpierw odrzucone (antyteza), a następnie wyjaśnienie jest podane jako synteza?
hakre
1
Uważam, że „obecna klasa” jest naprawdę problematyczna. Ponieważ tę kombinację słów można rozumieć zarówno jako „klasę, w której się selfznajduje” / „definicję klasy, jest ona dosłowną częścią”, jak również „klasę obiektu” (która w rzeczywistości byłaby static).
Jakumi
Co $this::?
James
1
@James - nie ma dobrego powodu, aby używać $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::.
ToolmakerSteve
461
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:
classPerson{publicstaticfunction status(){self::getStatus();}protectedstaticfunction 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:
classDeceasedextendsPerson{protectedstaticfunction 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ć.
„Calling Deceased :: status () spodziewalibyśmy się, że„ Person is Dead ””. Nie. To jest wywołanie funkcji statycznej, więc nie ma w tym udziału polimorfizm.
cquezel
2
Ze wszystkich wad PHP, nie sądzę, żeby to było w ogóle szaleństwo. W jaki inny sposób pozwolą programistom na oznaczanie metod dla bieżącej klasy (w przeciwieństwie do wyszukiwania ich w vtable)? Gdyby nazwali go inaczej (być może z wiodącymi podkreśleniami), ludzie, którzy chcą tej funkcji, skrytykowaliby ją za brzydkość. W przeciwnym razie, jakikolwiek rozsądny wyraz, którego mogliby użyć, wydaje się, że zawsze łatwo byłoby pomylić ludzi, którzy krytykowaliby go za „szalone” zachowanie, prawdopodobnie nieświadome tego, jak działa metoda wysyłania.
tne
2
Przykład wydaje mi się mylący: widzę getStatusmetodę jako taką, którą wywołałbym dla instancji klasy, a nie dla klasy.
Jānis Elmeris,
1
@Sqoo - powiedzenie „NIE UŻYWAJ self ::, użyj static ::” to dziwny punkt do zrobienia - celowo nie są to te same operacje. Wydaje mi się, że tak naprawdę chodzi o to, aby „było wyraźniej, gdybyś użył rzeczywistej nazwy klasy„ MyClass :: ”, a nie„ self :: ” . Oznacza to, że jeśli chcesz się zachowywać self::, możesz uzyskać to mniej myląco, używając konkretnej nazwy klasy, np MyClass::.
ToolmakerSteve
248
Aby naprawdę zrozumieć, o czym mówimy, gdy mówimy o selfkontra $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 .
Klasy i przedmioty, koncepcyjnie
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ę:
Jak widać, w tej klasie jest wywołana właściwość $namei wywołana metoda (funkcja) sayHello().
To bardzo ważne, aby pamiętać, że klasa jest strukturą statyczną. Co oznacza, że Personraz 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 =newPerson;
$adam =newPerson;
$bob->name ='Bob';
echo $adam->name;// "my name"
Tworzymy nowe wystąpienia klasy za pomocą newoperatora.
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 instanceofokreśloną klasą: $bob instanceof Personktóra zwraca wartość logiczną, jeśli $bobinstancja została wykonana przy użyciu Personklasy, lub elementu potomnego Person.
Definiowanie stanu
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.
classFoo{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ę.
classFoo{publicstatic $bar =1;}
Metody - są to funkcje, które każda instancja będzie zawierała (i działała na instancjach).
classFoo{publicfunction 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.
classFoo{publicstaticfunction bar(){}}
Stałe - stałe klasowe. Nie wchodzę tutaj głębiej, ale dodajemy dla kompletności:
classFoo{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).
Stan i metody
Wewnątrz metody instancja obiektu jest reprezentowana przez $thiszmienną. 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, $thiszmienna 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:
Państwo przystępujące
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 wystąpienia / klasy
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 =newPerson;
echo $bob->name;
Ważne jest, aby pamiętać, że wywoływanie Person->foonie ma sensu (ponieważ Personjest 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 $thisnie jest zdefiniowany w wywołaniu statycznym.
From Inside Of Instance / Class
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.
Wywołanie Foo::bar()wywoła baz()metodę statycznie, a więc $thisbędzie nie być wypełniane. Warto zauważyć, że w najnowszych wersjach PHP (5.3+) spowoduje to E_STRICTbłą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.
Skrótowe słowa kluczowe
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 Fooklasie (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 staticzamiast nazwy klasy pozwala nam ustalić, skąd pochodzi połączenie, a nie na bieżącym poziomie.
Przykłady
Najłatwiej to zrozumieć, zaczynając od kilku przykładów. Wybierzmy klasę:
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ć:
Licznik identyfikatorów jest więc współużytkowany przez obie instancje i dzieci (ponieważ korzystamy selfz 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.
Słowo ostrzeżenia # 1
Zauważ, że kontekst wywołania określa, czy instancja jest używana. W związku z tym:
Teraz jest tu naprawdę dziwnie. Wzywamy inną klasę, ale metoda $thisprzekazywana 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, selfi parent).
Słowo ostrzeżenia # 2
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.
Słowo ostrzeżenia # 3
Ogólnie rzecz biorąc, będziesz chciał użyć tak zwanego późnego wiązania statycznego, używając staticzamiast self. Pamiętaj jednak, że to nie to samo, dlatego powiedzenie „zawsze używaj staticzamiast zamiast selfjest 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.
TL / DR
Szkoda, wróć i przeczytaj. To może być za długie, ale tak długo, ponieważ jest to złożony temat
TL / DR # 2
Ok dobrze. W skrócie, selfsłuży do odwołania do bieżącej nazwy klasy w klasie, gdzie $thisodnosi się do bieżącej instancji obiektu . Pamiętaj, że selfjest to skrót do kopiowania / wklejania. Możesz go bezpiecznie zastąpić nazwą klasy i będzie dobrze działać. Ale $thisjest zmienną dynamiczną, której nie można ustalić z wyprzedzeniem (i może nawet nie być twoją klasą).
TL / DR # 3
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.).
Słowo ostrzeżenia # 1: $ to nie zostanie zdefiniowane podczas wywoływania metody statycznej: 3v4l.org/9kr0e
Mark Achée
Cóż ... $thisnie 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.
Mark Achée
2
Po całkowitym przeczytaniu długiego opisu poczułem lenistwo, aby przewinąć go ponownie, aby go głosować. Tylko żartowałem, głosowałem za tym: D. Dzięki, to jest bardzo przydatne.
Mr_Green
3
dobrze byłoby dodać jasne wyjaśnienie różnicy między self :: $ property a self :: property; Myślę, że to też jest dość mylące
Tommaso Barbugli
1
WoC # 1 zachowuje się inaczej niż PHP 7. Jak Foo::isFoo()to się nazywa statycznie, $thisnie zostanie zdefiniowane. To moim zdaniem bardziej intuicyjne zachowanie. - Podaje się inny wynik, jeśli Barmiał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).
Kontrollfreak
117
self(nie $ self) odnosi się do typu klasy, gdzie $thisodnosi się do bieżącej instancji klasy. selfjest przeznaczony do użycia w statycznych funkcjach członka, aby umożliwić ci dostęp do statycznych zmiennych członka. $thisjest używany w niestatycznych funkcjach składowych i jest odwołaniem do instancji klasy, w której wywołano funkcję składową.
Ponieważ thisjest to obiekt, używasz go w następujący sposób:$this->member
Ponieważ selfnie 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 =newPerson();
$ 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).
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?
Po pierwsze, dołączanie funkcji do obiektów pomaga utrzymać porządek, dzięki czemu wiesz, gdzie je znaleźć.
Po drugie, zapobiega konfliktom nazw. W dużym projekcie prawdopodobnie dwóch programistów utworzy funkcje getName (). Jeśli jeden tworzy ClassName1 :: getName (), a drugi tworzy ClassName2 :: getName (), nie stanowi to żadnego problemu. Bez konfliktu. Metody statyczne!
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;
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:
classParentClass{function test(){self::who();// will output 'parent'
$this->who();// will output 'child'}function who(){
echo 'parent';}}classChildClassextendsParentClass{function who(){
echo 'child';}}
$obj =newChildClass();
$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 $thisodnosi się do klasy bieżącego obiektu .
Dlatego powinieneś używać self tylko wtedy, gdy $thisnie jest ono dostępne lub gdy nie chcesz pozwolić klasom potomnym na zastąpienie bieżącej metody.
Według http://www.php.net/manual/en/language.oop5.static.php nie ma $self. Istnieje tylko $thisodniesienie 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ą.
Sugestia: Przeczytaj tę odpowiedź, gdy potkniesz się na kwas.
a20
16
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::classmembera$this->classmember .
Na przykład oba poniższe przykłady działają bezbłędnie, niezależnie od tego, czy używasz, self::czy$this->
Szczególnie zabawne jest rozpoczęcie odpowiedzi od „Wierzę, że pytanie nie brzmiało, czy można wywołać statycznego członka klasy, wywołując ClassName :: staticMember. Pytanie dotyczyło różnicy między używaniem self :: classmember a $ this-> classmember” a następnie przejdziecie w ogóle do żadnych różnic. W rzeczywistości pokazujesz przykład, w którym obie opcje działają identycznie. -1
Buttle Butkus
Mimo to przydatne. Zakres dotyczył rozdzielczości i ta część nie jest jasna w podręczniku php. Nadal uważam, że jest to przydatne
renoirb
2
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
K-Gun
16
self odnosi się do bieżącej klasy (w której się nazywa),
$thisodnosi się do bieżącego obiektu. Możesz użyć statycznego zamiast siebie. Zobacz przykład:
Wskaźnik obiektu $thisodnosi się do bieżącego obiektu.
Wartość klasy staticodnosi się do bieżącego obiektu.
Wartość klasy selfodnosi się do dokładnej klasy, w której została zdefiniowana.
Wartość klasy parentodnosi 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 {publicstaticfunction newStaticClass(){returnnewstatic;}publicstaticfunction newSelfClass(){returnnewself;}publicfunction newThisClass(){returnnew $this;}}class B extends A
{publicfunction newParentClass(){returnnew 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());// Aclass C extends B
{publicstaticfunction newSelfClass(){returnnewself;}}
$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 staticlub $this. Są jednak chwile, kiedy potrzebujesz,self ponieważ chcesz oryginalnej klasy bez względu na to, co ją rozszerza. (Bardzo, bardzo rzadko)
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 =newTleb\Benchmark\Benchmark(2000000);classFoo{publicfunction calling_this(){
$this->called();}publicfunction calling_self(){self::called();}publicfunction calling_static(){static::called();}publicstaticfunction called(){}}
$b->add('$this->',function(){ $foo =newFoo; $foo->calling_this();});
$b->add('self::',function(){ $foo =newFoo; $foo->calling_self();});
$b->add('static::',function(){ $foo =newFoo; $foo->calling_static();});
$b->run();
Wywołanie funkcji braku operacji 2 000 000 razy trwa 1s. Uwielbiam PHP.
rr-
Dobry stary PHP. :) Ale połączenie = 0,001 ms. Jest aż tak źle?
tleb
Wierzę, że to (i podobne rzeczy) powoduje, że rzeczy takie jak ORM są powolne, chyba że buforujesz rzeczy, a statyczne generatory witryn to coś.
rr-
2
Teoretycznie powinien zająć 1 cykl zegara procesora, co sprawia, że w 1 / 2e9 s = 0.5 nstych dniach
Buddy
Po prostu przeczytaj ponownie moją odpowiedź. Uważaj: to także tworzy klasę . Nie wiem, dlaczego nie useużyłem słowa kluczowego tbh, ale nie mam już PHP, aby powtórzyć test porównawczy, i nie mam ochoty go ponownie instalować.
tleb
13
W przypadku selfużycia z ::operatorem odnosi się do bieżącej klasy, co można wykonać zarówno w kontekście statycznym, jak i niestatycznym. $thisodnosi się do samego obiektu. Ponadto całkowicie legalne jest $thiswywoływanie metod statycznych (ale nie odwoływanie się do pól).
Natrafiłem na to samo pytanie, a prosta odpowiedź brzmi:
$this wymaga wystąpienia klasy
self:: nie
Ilekroć 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ż $thiszawsze wymaga utworzenia obiektu.
$thisodnosi się do bieżącego obiektu klasy, selfodnosi 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 statici this for none-static members or methods.
również w scenariuszu podrzędnym / nadrzędnym self / parentstosuje 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.
classFoo{const NAME ='Foo';//Always Foo::NAME (Foo) due to selfprotectedstatic $staticName =self::NAME;publicfunction __construct(){
echo $this::NAME;}publicfunction getStaticName(){
echo $this::$staticName;}}classBarextendsFoo{const NAME ='FooBar';/**
* override getStaticName to output Bar::NAME
*/publicfunction getStaticName(){
$this::$staticName = $this::NAME;
parent::getStaticName();}}
$foo =newFoo;//outputs Foo
$bar =newBar;//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::CONSTANTnpecho $foo::NAME; . W przeciwieństwie do$this::NAME;
Użyj, selfjeś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 thisdo perspektywy obiektu.
Według php.net istnieją trzy specjalne słowa kluczowe w tym kontekście: self, parenti static. Służą do uzyskiwania dostępu do właściwości lub metod z definicji klasy.
$thisz drugiej strony służy do wywoływania instancji i metod dowolnej klasy, o ile klasa ta jest dostępna.
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;publicfunction 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());
Odpowiedzi:
Krótka odpowiedź
Pełna odpowiedź
Oto przykład poprawnego użycia
$this
iself
dla niestatycznych i statycznych zmiennych składowych:Oto przykład nieprawidłowego użycia
$this
iself
dla niestatycznych i statycznych zmiennych składowych:Oto przykład polimorfizmu ze
$this
dla funkcji składowych:Oto przykład tłumienia zachowania polimorficznego przy użyciu
self
funkcji składowych:Od http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Przez http://board.phpbuilder.com/member.php?145249-laserlight
źródło
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żeszself::methodName()
także wywołać bieżącą implementację klasy metody.Spowoduje to:
sayHello()
używa$this
wskaźnika, więc vtable jest wywoływany do wywołaniaGeek::getTitle()
.sayGoodbye()
używaself::getTitle()
, więc vtable nie jest używane iPerson::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.źródło
self
znajduje” / „definicję klasy, jest ona dosłowną częścią”, jak również „klasę obiektu” (która w rzeczywistości byłabystatic
).$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::
lubstatic::
.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:Jeśli zadzwonimy
Person::status()
, zobaczymy „Osoba żyje”. Zastanówmy się teraz, co się stanie, gdy stworzymy klasę, która odziedziczy po tym: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łanieself::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 gdystatic::
odnosi się do klasyźródło
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, npMyClass::
.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 .
Klasy i przedmioty, koncepcyjnie
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ę:
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.
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życiuPerson
klasy, lub elementu potomnegoPerson
.Definiowanie stanu
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.
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ę.
Metody - są to funkcje, które każda instancja będzie zawierała (i działała na instancjach).
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.
Stałe - stałe klasowe. Nie wchodzę tutaj głębiej, ale dodajemy dla kompletności:
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).
Stan i metody
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:
Państwo przystępujące
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 wystąpienia / klasy
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.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.Dodatkowo możemy wywołać metodę statyczną na obiekcie w ten sam sposób:
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:Dlatego
$this
nie jest zdefiniowany w wywołaniu statycznym.From Inside Of Instance / Class
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.Wywołanie
bar()
metody$foo
(instancjaFoo
) 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:Wywołanie
Foo::bar()
wywołabaz()
metodę statycznie, a więc$this
będzie nie być wypełniane. Warto zauważyć, że w najnowszych wersjach PHP (5.3+) spowoduje toE_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 jakostatic
, 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ócitrue
, ponieważ wywołanie „statyczne” odbywa się w kontekście instancji.Ma sens? Tak nie myślałem. To jest mylące.
Skrótowe słowa kluczowe
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. Takself::baz()
samo jestFoo::baz()
wFoo
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życiustatic
zamiast nazwy klasy pozwala nam ustalić, skąd pochodzi połączenie, a nie na bieżącym poziomie.Przykłady
Najłatwiej to zrozumieć, zaczynając od kilku przykładów. Wybierzmy klasę:
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ć:
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 korzystalistatic
, moglibyśmy zastąpić go w klasie potomnej).Pamiętaj, że za każdym razem wykonujemy metodę
Person::getName()
instancji . Ale używamyparent::getName()
do tego w jednym z przypadków (przypadek podrzędny). To sprawia, że to podejście jest potężne.Słowo ostrzeżenia # 1
Zauważ, że kontekst wywołania określa, czy instancja jest używana. W związku z tym:
Nie zawsze jest to prawda.
Teraz jest tu naprawdę dziwnie. Wzywamy inną klasę, ale metoda
$this
przekazywana doFoo::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 kluczowestatic
,self
iparent
).Słowo ostrzeżenia # 2
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.
Słowo ostrzeżenia # 3
Ogólnie rzecz biorąc, będziesz chciał użyć tak zwanego późnego wiązania statycznego, używając
static
zamiastself
. Pamiętaj jednak, że to nie to samo, dlatego powiedzenie „zawsze używajstatic
zamiast zamiastself
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.TL / DR
Szkoda, wróć i przeczytaj. To może być za długie, ale tak długo, ponieważ jest to złożony temat
TL / DR # 2
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, żeself
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ą).TL / DR # 3
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.).źródło
$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śliBar
miałby zostać przedłużonyFoo
. Wtedy wywołanieFoo::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
źródło
$this->
jest używany w odniesieniu do określonego wystąpienia zmiennych klasy (zmiennych składowych) lub metod.$ 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:
Podobnie jak obiekty mają konstruktory, mają także destruktory, które są wykonywane, gdy obiekt umiera lub jest rozbrojony:
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:
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:
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ć :)
źródło
$
znaku. Na przykładself::$templates_path
Z tego postu na blogu :
źródło
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()
zself::method()
dowolnego miejsca, niezależnie od tego czymethod()
jest static czy nie. Którego powinieneś użyć?Rozważ ten kod:
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.źródło
Wewnątrz definicji klasy
$this
odnosi się do bieżącego obiektu, aself
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
.źródło
źródło
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ą.źródło
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żywaniemself::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->
źródło
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:Wyjście: dziecko nadrzędne
źródło
$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.
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)źródło
Ponieważ nikt tutaj nie mówił o występach, oto mały test, który zrobiłem (5.6):
To są wyniki dla 2 000 000 przebiegów, a oto kod, którego użyłem:
źródło
1 / 2e9 s = 0.5 ns
tych dniachuse
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ć.W przypadku
self
użycia z::
operatorem odnosi się do bieżącej klasy, co można wykonać zarówno w kontekście statycznym, jak i niestatycznym.$this
odnosi się do samego obiektu. Ponadto całkowicie legalne jest$this
wywoływanie metod statycznych (ale nie odwoływanie się do pól).źródło
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.źródło
$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
ithis 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.źródło
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.http://ideone.com/7etRHy
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;
źródło
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żyjthis
do perspektywy obiektu.źródło
Przypadek 1: Użyj
self
może być użyte dla stałych klasJeśli chcesz wywołać go poza klasą, użyj,
classA::POUNDS_TO_KILOGRAMS
aby uzyskać dostęp do stałychPrzypadek 2: Dla właściwości statycznych
źródło
Według php.net istnieją trzy specjalne słowa kluczowe w tym kontekście:
self
,parent
istatic
. Służą do uzyskiwania dostępu do właściwości lub metod z definicji klasy.$this
z drugiej strony służy do wywoływania instancji i metod dowolnej klasy, o ile klasa ta jest dostępna.źródło
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.
źródło