Ich werde fragen, was der Unterschied ist zwischen: cont A; $ this-> A und self :: A
timmz
Antworten:
1728
Kurze Antwort
Verwenden Sie $thisdiese Option , um auf das aktuelle Objekt zu verweisen. Verwenden Sie selfdiese Option , um auf die aktuelle Klasse zu verweisen. Mit anderen Worten,
$this->memberfür nicht statische Elemente verwenden, self::$memberfür statische Elemente verwenden.
Vollständige Antwort
Hier ist ein Beispiel für die korrekte Verwendung von $thisund selffür nicht statische und statische Elementvariablen:
<?php
class X {private $non_static_member =1;privatestatic $static_member =2;function __construct(){
echo $this->non_static_member .' '.self::$static_member;}}new X();?>
Hier ist ein Beispiel für die falsche Verwendung von $thisund selffür nicht statische und statische Elementvariablen:
<?php
class X {private $non_static_member =1;privatestatic $static_member =2;function __construct(){
echo self::$non_static_member .' '. $this->static_member;}}new X();?>
Hier ist ein Beispiel für Polymorphismus mit $thisfür Elementfunktionen:
<?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();?>
Hier ist ein Beispiel für die Unterdrückung des polymorphen Verhaltens mithilfe selfvon Elementfunktionen:
<?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();?>
Die Idee ist, dass $this->foo()die foo()Member-Funktion aufgerufen wird, was auch immer der genaue Typ des aktuellen Objekts ist. Wenn das Objekt von ist type X, ruft es somit auf X::foo(). Wenn das Objekt von ist type Y, ruft es auf Y::foo(). Aber mit self :: foo () X::foo()wird immer aufgerufen.
Diese Antwort ist zu simpel. Wie in anderen Antworten angegeben, selfwird mit dem Bereichsauflösungsoperator verwendet ::, um auf die aktuelle Klasse zu verweisen. Dies kann sowohl in statischen als auch in nicht statischen Kontexten erfolgen. Darüber hinaus ist es völlig legal, $thisstatische Methoden aufzurufen (aber keine Referenzfelder).
Artefacto
50
Erwägen Sie auch die Verwendung von static :: anstelle von :: self, wenn Sie 5.3+ verwenden. Andernfalls kann es zu unerklärlichen Kopfschmerzen kommen. In meiner Antwort unten erfahren Sie, warum.
Sqoo
25
-1. Diese Antwort ist irreführend. Lesen Sie die anderen Antworten, um weitere Informationen zu erhalten.
Pacerier
6
Es mag zu stark vereinfacht sein, aber es hat meine grundlegende Frage beantwortet, ohne dass mein Kopf explodiert. Ich habe einige weitere Informationen erhalten, die ich weiter unten als hilfreich empfand, aber im Moment habe ich nur versucht herauszufinden, warum ich meine Klassenattribute mit $ this-> attrib und die Klassenkonstanten mit self :: constant getroffen habe. Dies half mir, das besser zu verstehen
MydKnight
Was ist mit $this::?
James
742
Das Schlüsselwort self bezieht sich NICHT nur auf die 'aktuelle Klasse', zumindest nicht in einer Weise, die Sie auf statische Mitglieder beschränkt. selfBietet im Kontext eines nicht statischen Elements auch eine Möglichkeit, die vtable ( siehe Wiki auf vtable ) für das aktuelle Objekt zu umgehen . So wie Sie parent::methodName()die übergeordnete Version einer Funktion aufrufen können, können Sie auch self::methodName()die aktuelle Klassenimplementierung einer Methode aufrufen.
Hallo, ich bin Ludwig der Geek
Auf Wiedersehen von Ludwig die Person
sayHello()Verwendet den $thisZeiger, sodass die vtable zum Aufrufen aufgerufen wird Geek::getTitle().
sayGoodbye()verwendet self::getTitle(), daher wird die vtable nicht verwendet und Person::getTitle()aufgerufen. In beiden Fällen handelt es sich um die Methode eines instanziierten Objekts und wir haben Zugriff auf den $thisZeiger innerhalb der aufgerufenen Funktionen.
Diese Antwort wäre sogar noch besser, wenn Sie eher mit einer allgemeinen Regel als mit einer Ausnahme beginnen würden. Es ist eine Frage des Stils, nicht des technischen Fachwissens. Dies ist das beste Beispiel, das ich je für den Unterschied zwischen self :: und $ this-> gesehen habe, aber es ist eine Schande, dies zu verbergen, indem man zuerst einen Begriff widerlegt.
Adjwilli
3
@adjwilli: Warum ist das ein schlechter Stil? Erhöht es nicht das Bewusstsein, wenn die Erwartung (These) des OP zuerst missbilligt wird (Antithese) und dann die Erklärung als Synthese gegeben wird?
hakre
1
Ich finde "aktuelle Klasse" wirklich problematisch. Da diese Wortkombination sowohl als "die Klasse, in der selfsich befindet" / "die Klassendefinition, die ein wörtlicher Teil von" ist, als auch als "die Klasse des Objekts" (was tatsächlich der Fall wäre static) verstanden werden kann.
Jakumi
Was ist mit $this::?
James
1
@ James - es gibt keinen guten Grund zu verwenden $this::; Alle möglichen Fälle werden bereits durch häufig verwendete Syntaxen abgedeckt. Je nachdem , was Sie meinen, Verwendung $this->, self::oder static::.
ToolmakerSteve
461
NICHT VERWENDEN self::, verwendenstatic::
Es gibt noch einen weiteren Aspekt des Selbst: der erwähnenswert ist. Ärgerlicherweise self::bezieht sich der Geltungsbereich zum Zeitpunkt der Definition und nicht zum Zeitpunkt der Ausführung . Betrachten Sie diese einfache Klasse mit zwei Methoden:
classPerson{publicstaticfunction status(){self::getStatus();}protectedstaticfunction getStatus(){
echo "Person is alive";}}
Wenn wir anrufen, sehen Person::status()wir "Person lebt". Überlegen Sie nun, was passiert, wenn wir eine Klasse erstellen, die davon erbt:
classDeceasedextendsPerson{protectedstaticfunction getStatus(){
echo "Person is deceased";}}
Beim Aufrufen wird Deceased::status()erwartet, dass "Person ist verstorben" angezeigt wird. Wir sehen jedoch "Person lebt", da der Bereich die ursprüngliche Methodendefinition enthält, als der Aufruf von self::getStatus()definiert wurde.
PHP 5.3 hat eine Lösung. Der static::Auflösungsoperator implementiert "späte statische Bindung", was eine ausgefallene Art zu sagen ist, dass sie an den Umfang der aufgerufenen Klasse gebunden ist. Ändern Sie die Zeile in status()zu static::getStatus() , und die Ergebnisse sind das, was man erwarten würde. In älteren Versionen von PHP müssen Sie einen Kludge finden, um dies zu tun.
"Wenn wir Deceased :: status () aufrufen, erwarten wir" Person ist verstorben "". Nein. Dies ist ein statischer Funktionsaufruf, sodass kein Polymorphismus vorliegt.
Cquezel
2
Von allen Fehlern von PHP halte ich das überhaupt nicht für verrückt. Wie sonst würden sie es Codierern erlauben, Methoden für die aktuelle Klasse zu bestimmen (anstatt sie in der vtable nachzuschlagen)? Wenn sie es anders benannt hätten (vielleicht mit führenden Unterstrichen), würden Leute, die dieses Feature wollen, es als hässlich kritisieren. Andernfalls scheint es immer leicht verwirrte Leute zu geben, die es als "wahnsinniges" Verhalten kritisieren, ohne zu wissen, wie der Methodenversand überhaupt funktioniert.
Der
2
Das Beispiel erscheint mir verwirrend: Ich sehe die getStatusMethode als eine, die ich für eine Klasseninstanz aufrufen würde, nicht für eine Klasse.
Jānis Elmeris
1
@Sqoo - zu sagen " VERWENDEN SIE NICHT self ::, verwenden Sie static ::" ist ein seltsamer Punkt - das sind absichtlich nicht die gleichen Operationen. Ich denke, der Punkt, den Sie wirklich ansprechen, ist: "Es ist klarer, wenn Sie den tatsächlichen Klassennamen 'MyClass ::' anstelle von 'self ::' verwenden . Das heißt, wenn Sie das Verhalten von wollen self::, können Sie das weniger bekommen verwirrenderweise unter Verwendung des spezifischen Klassennamens, z MyClass::. B.
ToolmakerSteve
248
Um wirklich zu verstehen, worüber wir sprechen, wenn wir über selfversus sprechen $this, müssen wir uns tatsächlich mit dem befassen, was auf konzeptioneller und praktischer Ebene vor sich geht. Ich habe nicht das Gefühl, dass eine der Antworten dies angemessen macht. Hier ist mein Versuch.
Lassen Sie uns zunächst darüber sprechen, was eine Klasse und ein Objekt sind.
Klassen und Objekte, konzeptionell
Was ist eine Klasse ? Viele Leute definieren es als Blaupause oder Vorlage für ein Objekt. In der Tat können Sie hier mehr über Klassen in PHP lesen . Und bis zu einem gewissen Grad ist es das wirklich. Schauen wir uns eine Klasse an:
Wie Sie sehen können, gibt es für diese Klasse eine Eigenschaft namens $nameund eine Methode (Funktion) sayHello().
Es ist sehr wichtig zu beachten, dass die Klasse eine statische Struktur ist. Dies bedeutet, dass die Personeinmal definierte Klasse überall, wo Sie sie betrachten, immer dieselbe ist.
Ein Objekt hingegen ist eine sogenannte Instanz einer Klasse. Das bedeutet, dass wir den "Entwurf" der Klasse nehmen und daraus eine dynamische Kopie erstellen. Diese Kopie ist jetzt speziell an die Variable gebunden, in der sie gespeichert ist. Daher sind alle Änderungen an einer Instanz lokal für diese Instanz.
$bob =newPerson;
$adam =newPerson;
$bob->name ='Bob';
echo $adam->name;// "my name"
Wir erstellen neue Instanzen einer Klasse mit dem newOperator.
Daher sagen wir, dass eine Klasse eine globale Struktur und ein Objekt eine lokale Struktur ist. Mach dir keine Sorgen um diese lustige ->Syntax, wir werden gleich darauf eingehen.
Eine andere Sache, über die wir sprechen sollten, ist, dass wir überprüfen können , ob eine Instanz instanceofeine bestimmte Klasse ist: $bob instanceof Persondie einen Booleschen Wert zurückgibt, wenn die $bobInstanz mit der PersonKlasse oder einem untergeordneten Element von erstellt wurde Person.
Zustand definieren
Lassen Sie uns ein wenig untersuchen, was eine Klasse tatsächlich enthält. Es gibt 5 Arten von "Dingen", die eine Klasse enthält:
Eigenschaften - Stellen Sie sich diese als Variablen vor, die jede Instanz enthalten wird.
classFoo{public $bar =1;}
Statische Eigenschaften - Stellen Sie sich diese als Variablen vor, die auf Klassenebene gemeinsam genutzt werden. Dies bedeutet, dass sie niemals von jeder Instanz kopiert werden.
classFoo{publicstatic $bar =1;}
Methoden - Dies sind Funktionen, die jede Instanz enthält (und mit Instanzen arbeitet).
classFoo{publicfunction bar(){}}
Statische Methoden - Dies sind Funktionen, die von der gesamten Klasse gemeinsam genutzt werden. Sie arbeiten nicht mit Instanzen, sondern nur mit den statischen Eigenschaften.
classFoo{publicstaticfunction bar(){}}
Konstanten - Klassenaufgelöste Konstanten. Hier nicht tiefer gehen, sondern der Vollständigkeit halber hinzufügen:
classFoo{const BAR =1;}
Im Grunde speichern wir Informationen über den Klassen- und Objektcontainer mithilfe von "Hinweisen" zu statischen Informationen, die angeben, ob die Informationen gemeinsam genutzt werden (und daher statisch sind) oder nicht (und daher dynamisch).
Zustand und Methoden
Innerhalb einer Methode wird die Instanz eines Objekts durch die $thisVariable dargestellt. Der aktuelle Status dieses Objekts ist vorhanden, und das Mutieren (Ändern) einer Eigenschaft führt zu einer Änderung dieser Instanz (jedoch nicht anderer).
Wenn eine Methode statisch aufgerufen wird, ist die $thisVariable nicht definiert . Dies liegt daran, dass einem statischen Aufruf keine Instanz zugeordnet ist.
Das Interessante dabei ist, wie statische Anrufe getätigt werden. Sprechen wir also darüber, wie wir auf den Staat zugreifen:
Zugriffsstatus
Nachdem wir diesen Status gespeichert haben, müssen wir darauf zugreifen. Dies kann etwas knifflig werden (oder weit mehr als ein bisschen). Teilen wir dies also in zwei Gesichtspunkte auf: von außerhalb einer Instanz / Klasse (z. B. von einem normalen Funktionsaufruf oder vom globalen Bereich) und innerhalb einer Instanz / class (aus einer Methode für das Objekt).
Von außerhalb einer Instanz / Klasse
Von außerhalb einer Instanz / Klasse sind unsere Regeln recht einfach und vorhersehbar. Wir haben zwei Operatoren und jeder teilt uns sofort mit, ob es sich um eine Instanz oder eine statische Klasse handelt:
->- Objektoperator - Dies wird immer verwendet, wenn wir auf eine Instanz zugreifen.
$bob =newPerson;
echo $bob->name;
Es ist wichtig zu beachten, dass das Aufrufen Person->fookeinen Sinn ergibt (da Persones sich um eine Klasse handelt, nicht um eine Instanz). Daher ist dies ein Analysefehler.
::- Bereichsauflösungsoperator - Wird immer verwendet, um auf eine statische Eigenschaft oder Methode der Klasse zuzugreifen.
echo Foo::bar()
Darüber hinaus können wir eine statische Methode für ein Objekt auf dieselbe Weise aufrufen:
echo $foo::bar()
Es ist äußerst wichtig zu beachten, dass die Instanz des Objekts , wenn wir dies von außen tun , vor der bar()Methode verborgen bleibt . Das heißt, es ist genau das gleiche wie beim Laufen:
$class = get_class($foo);
$class::bar();
Daher $thisist im statischen Aufruf nicht definiert.
Aus dem Inneren einer Instanz / Klasse
Hier ändern sich die Dinge ein bisschen. Es werden dieselben Operatoren verwendet, aber ihre Bedeutung wird erheblich unscharf.
Der Objektoperator-> wird weiterhin verwendet, um den Instanzstatus des Objekts aufzurufen.
Der Aufruf Foo::bar()wird der Anruf baz()statisch Methode, und daher $thiswird nicht aufgefüllt werden. Es ist erwähnenswert, dass dies in neueren Versionen von PHP (5.3+) einen E_STRICTFehler auslöst , da wir nicht statische Methoden statisch aufrufen.
Innerhalb eines Instanzkontexts
In einem Instanzkontext hingegen ::hängen Anrufe, die mit ausgeführt werden, vom Empfänger des Anrufs ab (der Methode, die wir aufrufen). Wenn die Methode definiert ist als static, wird ein statischer Aufruf verwendet. Ist dies nicht der Fall, werden die Instanzinformationen weitergeleitet.
Wenn Sie sich also den obigen Code ansehen, $foo->bar()wird der Aufruf zurückgegeben true, da der "statische" Aufruf innerhalb eines Instanzkontexts erfolgt.
Sinn ergeben? Das habe ich nicht gedacht. Es ist verwirrend.
Tastenkürzel
Da das Zusammenbinden von Elementen mithilfe von Klassennamen ziemlich schmutzig ist, bietet PHP drei grundlegende "Verknüpfungs" -Schlüsselwörter, um die Auflösung des Bereichs zu vereinfachen.
self- Dies bezieht sich auf den aktuellen Klassennamen. Ist self::baz()also dasselbe wie Foo::baz()innerhalb der FooKlasse (jede Methode darauf).
parent - Dies bezieht sich auf das übergeordnete Element der aktuellen Klasse.
static- Dies bezieht sich auf die aufgerufene Klasse. Dank der Vererbung können untergeordnete Klassen Methoden und statische Eigenschaften überschreiben. staticWenn wir sie also anstelle eines Klassennamens aufrufen, können wir feststellen, woher der Anruf stammt und nicht auf der aktuellen Ebene.
Beispiele
Der einfachste Weg, dies zu verstehen, besteht darin, sich einige Beispiele anzusehen. Lassen Sie uns eine Klasse auswählen:
Jetzt betrachten wir hier auch die Vererbung. Ignorieren Sie für einen Moment, dass dies ein schlechtes Objektmodell ist, aber schauen wir uns an, was passiert, wenn wir damit spielen:
Der ID-Zähler wird also von beiden Instanzen und den untergeordneten Elementen gemeinsam genutzt (da wir selffür den Zugriff darauf verwenden. Wenn wir ihn verwenden static, können wir ihn in einer untergeordneten Klasse überschreiben).
var_dump($bob->getName());// Bob
var_dump($adam->getName());// Adam
var_dump($billy->getName());// child: Billy
Beachten Sie, dass wir die Person::getName()Instanzmethode jedes Mal ausführen . Aber wir verwenden das parent::getName(), um es in einem der Fälle zu tun (dem untergeordneten Fall). Dies macht diesen Ansatz leistungsfähig.
Wort der Vorsicht # 1
Beachten Sie, dass der aufrufende Kontext bestimmt, ob eine Instanz verwendet wird. Deshalb:
Jetzt ist es hier wirklich komisch. Wir rufen eine andere Klasse auf, aber die $this, die an die Foo::isFoo()Methode übergeben wird, ist die Instanz von $bar.
Dies kann alle möglichen Fehler und konzeptionelle WTF-Fehler verursachen. Also ich sehr empfehlen würde die Vermeidung ::Operator aus Instanzmethoden auf irgendetwas außer den drei virtuellen „short-cut“ keywords ( static, self, und parent).
Wort der Vorsicht # 2
Beachten Sie, dass statische Methoden und Eigenschaften von allen gemeinsam genutzt werden. Das macht sie im Grunde zu globalen Variablen. Mit den gleichen Problemen, die mit Globals kommen. Daher würde ich sehr zögern, Informationen in statischen Methoden / Eigenschaften zu speichern, es sei denn, Sie sind damit einverstanden, dass sie wirklich global sind.
Wort der Vorsicht # 3
Im Allgemeinen möchten Sie das verwenden, was als Late-Static-Binding bezeichnet wird, indem Sie staticanstelle von verwenden self. Beachten Sie jedoch, dass sie nicht dasselbe sind. Daher ist es sehr kurzsichtig , zu sagen, dass immer verwenden staticstatt verwenden self. Halten Sie stattdessen an und überlegen Sie, welchen Anruf Sie tätigen möchten, und überlegen Sie, ob untergeordnete Klassen diese statische Auflösung überschreiben können Anruf.
TL / DR
Schade, geh zurück und lies es. Es mag zu lang sein, aber es ist so lang, weil dies ein komplexes Thema ist
TL / DR # 2
Ok, gut. Kurz gesagt, selfwird verwendet , um das Bezug der aktuellen Klassennamen innerhalb einer Klasse, in der, wie $thisauf die aktuelle Objekt verweist Instanz . Beachten Sie, dass dies selfeine Verknüpfung zum Kopieren / Einfügen ist. Sie können es sicher durch Ihren Klassennamen ersetzen, und es wird gut funktionieren. Ist $thisaber eine dynamische Variable, die nicht im Voraus bestimmt werden kann (und möglicherweise nicht einmal Ihre Klasse ist).
TL / DR # 3
Wenn der Objektoperator ( ->) verwendet wird, wissen Sie immer , dass es sich um eine Instanz handelt. Wenn der Scope-Resolution-Operator verwendet wird ( ::), benötigen Sie weitere Informationen zum Kontext (befinden wir uns bereits in einem Objektkontext? Befinden wir uns außerhalb eines Objekts? Usw.).
Wort der Vorsicht # 1: $ Dies wird nicht definiert, wenn eine statische Methode aufgerufen wird
Mark Achée
Nun ... $thiswird nicht definiert, wenn Sie "Strikte Standards" befolgen und keine statischen Methoden aufrufen, die nicht als statisch definiert sind. Ich sehe das Ergebnis, das Sie hier erklärt haben: 3v4l.org/WeHVM Einverstanden, wirklich komisch.
Mark Achée
2
Nachdem ich die lange Beschreibung vollständig gelesen hatte, fühlte ich mich faul, noch einmal nach oben zu scrollen, um sie zu verbessern. Nur ein Scherz, ich habe es positiv bewertet: D. Danke das ist sehr nützlich.
Mr_Green
3
Es wäre schön, eine klare Erklärung für den Unterschied zwischen self :: $ property und self :: property hinzuzufügen. Ich denke, das ist auch ziemlich verwirrend
Tommaso Barbugli
1
WoC # 1 verhält sich seit PHP 7 anders . Wie Foo::isFoo()statisch genannt, $thiswird es nicht definiert. Das ist meiner Meinung nach intuitiver. - Ein anderes Ergebnis ergibt sich, wenn Barvon Foo. Dann Foo::isFoo()würde sich der Aufruf tatsächlich im Instanzkontext befinden (nicht spezifisch für PHP7).
Kontrollfreak
117
self(nicht $ self) bezieht sich auf die Art der Klasse, wo , wie $thisauf die aktuelle bezieht Instanz der Klasse. selfdient zur Verwendung in statischen Elementfunktionen, um Ihnen den Zugriff auf statische Elementvariablen zu ermöglichen. $thiswird in nicht statischen Elementfunktionen verwendet und verweist auf die Instanz der Klasse, für die die Elementfunktion aufgerufen wurde.
Da thises sich um ein Objekt handelt, verwenden Sie es wie folgt:$this->member
Da selfes sich nicht um ein Objekt handelt, handelt es sich im Grunde genommen um einen Typ, der automatisch auf die aktuelle Klasse verweist. Sie verwenden ihn wie folgt:self::member
$this-> wird verwendet, um auf eine bestimmte Instanz der Variablen (Mitgliedsvariablen) oder Methoden einer Klasse zu verweisen.
Example:
$derek =newPerson();
$ derek ist jetzt eine bestimmte Instanz von Person. Jede Person hat einen Vor- und einen Nachnamen, aber $ derek hat einen bestimmten Vor- und Nachnamen (Derek Martin). Innerhalb der $ derek-Instanz können wir diese als $ this-> first_name und $ this-> last_name bezeichnen
ClassName :: wird verwendet, um auf diesen Klassentyp und seine statischen Variablen, statische Methoden, zu verweisen. Wenn es hilft, können Sie das Wort "statisch" mental durch "geteilt" ersetzen. Da sie gemeinsam genutzt werden, können sie nicht auf $ this verweisen, das sich auf eine bestimmte Instanz bezieht (nicht freigegeben). Statische Variablen (dh statische $ db_connection) können von allen Instanzen eines Objekttyps gemeinsam genutzt werden. Beispielsweise teilen sich alle Datenbankobjekte eine einzige Verbindung (statische $ Verbindung).
Statische Variablen Beispiel:
Stellen Sie sich vor, wir haben eine Datenbankklasse mit einer einzelnen Mitgliedsvariablen: static $ num_connections; Fügen Sie dies nun in den Konstruktor ein:
function __construct(){if(!isset $num_connections || $num_connections==null){
$num_connections=0;}else{
$num_connections++;}}
So wie Objekte Konstruktoren haben, haben sie auch Destruktoren, die ausgeführt werden, wenn das Objekt stirbt oder nicht gesetzt ist:
function __destruct(){
$num_connections--;}
Jedes Mal, wenn wir eine neue Instanz erstellen, wird unser Verbindungszähler um eins erhöht. Jedes Mal, wenn wir eine Instanz zerstören oder nicht mehr verwenden, wird der Verbindungszähler um eins verringert. Auf diese Weise können wir die Anzahl der Instanzen des Datenbankobjekts überwachen, mit denen wir arbeiten:
echo DB::num_connections;
Da $ num_connections statisch (gemeinsam genutzt) ist, gibt es die Gesamtzahl der aktiven Datenbankobjekte wieder. Möglicherweise wurde diese Technik verwendet, um Datenbankverbindungen für alle Instanzen einer Datenbankklasse freizugeben. Dies geschieht, weil das Erstellen der Datenbankverbindung sehr lange dauert. Daher ist es am besten, nur eine zu erstellen und diese freizugeben (dies wird als Singleton-Muster bezeichnet).
Statische Methoden (dh öffentliche statische View :: format_phone_number ($ digits)) können verwendet werden, OHNE zuerst eines dieser Objekte zu instanziieren (dh sie verweisen nicht intern auf $ this).
Wie Sie sehen können, weiß die öffentliche statische Funktion PrettyName nichts über das Objekt. Es funktioniert nur mit den Parametern, die Sie übergeben, wie eine normale Funktion, die nicht Teil eines Objekts ist. Warum also die Mühe machen, wenn wir es einfach nicht als Teil des Objekts haben könnten?
Wenn Sie Funktionen an Objekte anhängen, können Sie die Dinge besser organisieren, sodass Sie wissen, wo Sie sie finden.
Zweitens werden Namenskonflikte verhindert. In einem großen Projekt werden wahrscheinlich zwei Entwickler getName () -Funktionen erstellen. Wenn einer einen ClassName1 :: getName () erstellt und der andere ClassName2 :: getName () erstellt, ist dies überhaupt kein Problem. Kein Konflikt. Yay statische Methoden!
SELBST ::
Wenn Sie außerhalb des Objekts codieren , das über die statische Methode verfügt, auf die Sie verweisen möchten, müssen Sie es mit dem Objektnamen View :: format_phone_number ($ phone_number) aufrufen. Wenn Sie innerhalb des Objekts codieren , das über die statische Methode verfügt, auf die Sie verweisen möchten, können Sie entweder den Objektnamen View :: format_phone_number ($ pn) oder die Verknüpfung self :: format_phone_number ($ pn) verwenden
Gleiches gilt für statische Variablen:
Beispiel: View :: templates_path versus self :: templates_path
Wenn wir in der DB-Klasse auf eine statische Methode eines anderen Objekts verweisen, verwenden wir den Namen des Objekts:
Beispiel: Session :: getUsersOnline ();
Wenn die DB-Klasse jedoch auf ihre eigene statische Variable verweisen möchte, sagt sie einfach self:
Beispiel: self :: connection;
Gute Antwort. Ich möchte nur darauf hinweisen, dass Sie, wenn Sie sich auf ein statisches Attribut beziehen, ein $Zeichen verwenden müssen. Zum Beispielself::$templates_path
In PHP verwenden Sie das Schlüsselwort self, um auf statische Eigenschaften und Methoden zuzugreifen.
Das Problem ist , dass Sie ersetzen können , $this->method()mit self::method()überall, unabhängig davon , obmethod() statisch deklariert wird oder nicht. Welches sollten Sie also verwenden?
Betrachten Sie diesen Code:
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();
In diesem Beispiel self::who()wird immer 'parent' ausgegeben, während$this->who() von der Klasse des Objekts abhängt.
Jetzt können wir sehen, dass sich self auf die Klasse bezieht, in der es aufgerufen wird, während es $thissich auf die Klasse des aktuellen Objekts bezieht .
Daher sollten Sie self nur verwenden, wenn $thises nicht verfügbar ist oder wenn Sie nicht zulassen möchten, dass Nachkommenklassen die aktuelle Methode überschreiben.
Laut http://www.php.net/manual/en/language.oop5.static.php gibt es keine $self. Es gibt nur $this, um auf die aktuelle Instanz der Klasse (das Objekt) und self zu verweisen, die verwendet werden können, um auf statische Mitglieder einer Klasse zu verweisen. Hier kommt der Unterschied zwischen einer Objektinstanz und einer Klasse ins Spiel.
Vorschlag: Lesen Sie diese Antwort, wenn Sie mit Säure stolpern.
A20
16
Ich glaube, die Frage war nicht, ob Sie das statische Mitglied der Klasse durch Aufrufen aufrufen können ClassName::staticMember. Die Frage war, was der Unterschied zwischen self::classmemberund ist $this->classmember.
Zum Beispiel funktionieren beide der folgenden Beispiele fehlerfrei, unabhängig davon, ob Sie self::oder verwenden$this->
Es ist besonders lustig, dass Sie Ihre Antwort mit "Ich glaube, die Frage war nicht, ob Sie das statische Mitglied der Klasse durch Aufrufen von ClassName :: staticMember aufrufen können. Die Frage war, was der Unterschied zwischen der Verwendung von self :: classmember und $ this-> classmember ist." und dann zeigen Sie überhaupt keine Unterschiede. Tatsächlich zeigen Sie eine Instanz, in der die beiden Optionen identisch funktionieren. -1
Buttle Butkus
Trotzdem nützlich. Der Umfang war über Auflösung und dieser Teil ist im PHP-Handbuch nicht klar. Ich finde es immer noch nützlich
Renoirb
2
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
K-Gun
16
self bezieht sich auf die aktuelle Klasse (in der es heißt),
$thisverweist auf das aktuelle Objekt. Sie können statisch anstelle von selbst verwenden. Siehe das Beispiel:
Der Objektzeiger $thisauf bezieht sich auf das aktuelle Objekt.
Der Klassenwert staticbezieht sich auf das aktuelle Objekt.
Der Klassenwert selfbezieht sich auf die genaue Klasse, in der er definiert wurde.
Der Klassenwert parentbezieht sich auf das übergeordnete Element der genauen Klasse, in der es definiert wurde.
Siehe das folgende Beispiel, das die Überlastung zeigt.
<?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"
Meistens möchten Sie sich auf die aktuelle Klasse beziehen, weshalb Sie staticoder verwenden $this. Es gibt jedoch Zeiten, in denen Sie die ursprüngliche Klasse benötigen,self unabhängig davon, was sie erweitert. (Sehr, sehr selten)
Das sind die Ergebnisse für 2 000 000 Läufe, und hier ist der Code, den ich verwendet habe:
<?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();
Das 2 000 000-malige Aufrufen der No-Op-Funktion dauert 1s. Ich muss PHP lieben.
rr-
Gutes altes PHP. :) Aber ein Anruf = 0,001 ms. Ist es so schlimm?
Tleb
Ich glaube, dies (und ähnliche Dinge) ist der Grund, warum sich Dinge wie ORMs langsam anfühlen, es sei denn, Sie zwischenspeichern Dinge, und statische Site-Generatoren sind eine Sache.
rr-
2
Es sollte theoretisch 1 Prozessortaktzyklus dauern, was ungefähr in 1 / 2e9 s = 0.5 nsdiesen Tagen macht
Buddy
Lies einfach meine Antwort noch einmal. Seien Sie vorsichtig: Es erstellt auch die Klasse . Ich weiß nicht, warum ich das useSchlüsselwort tbh nicht verwendet habe, aber ich habe kein PHP mehr, um einen Benchmark zu wiederholen, und ich habe keine Lust, ihn neu zu installieren.
Tleb
13
Wenn selfes mit dem ::Operator verwendet wird, bezieht es sich auf die aktuelle Klasse, was sowohl in statischen als auch in nicht statischen Kontexten erfolgen kann. $thisbezieht sich auf das Objekt selbst. Darüber hinaus ist es völlig legal, $thisstatische Methoden aufzurufen (aber nicht auf Felder zu verweisen).
Ich bin auf dieselbe Frage gestoßen und die einfache Antwort lautet:
$this erfordert eine Instanz der Klasse
self:: nicht
Wenn Sie statische Methoden oder statische Attribute verwenden und diese aufrufen möchten, ohne dass ein Objekt der Klasse instanziiert wurde, müssen Sie self:sie aufrufen, da $thisimmer ein Objekt erstellt werden muss.
$thisbezieht sich auf das aktuelle Klassenobjekt, selfbezieht sich auf die aktuelle Klasse (kein Objekt). Die Klasse ist die Blaupause des Objekts. Sie definieren also eine Klasse, aber Sie konstruieren Objekte.
Also mit anderen Worten, verwenden Sie self for static undthis for none-static members or methods .
Auch im Child / Parent-Szenario self / parentwird meistens verwendet, um untergeordnete und übergeordnete Klassenmitglieder und -methoden zu identifizieren.
Nur zu Informationszwecken, ab PHP 5.3, wenn mit instanziierten Objekten gearbeitet wird, um den aktuellen Bereichswert zu erhalten static::, kann man alternativ $this::wie folgt verwenden.
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
Die Verwendung des obigen Codes ist keine übliche oder empfohlene Vorgehensweise, sondern dient lediglich der Veranschaulichung seiner Verwendung und dient eher als "Wussten Sie, dass?" in Bezug auf die Frage des Originalplakats.
Es repräsentiert auch die Verwendung von $object::CONSTANTzum Beispiel echo $foo::NAME;im Gegensatz zu$this::NAME;
Verwenden selfSie diese Option, wenn Sie eine Methode einer Klasse aufrufen möchten, ohne ein Objekt / eine Instanz dieser Klasse zu erstellen, wodurch RAM gespart wird (verwenden Sie manchmal self für diesen Zweck). Mit anderen Worten, es wird tatsächlich eine Methode statisch aufgerufen. Verwendung thisfür Objektperspektive.
Nach php.net gibt es drei spezielle Schlüsselwörter in diesem Zusammenhang: self, parentund static. Sie werden verwendet, um über die Klassendefinition auf Eigenschaften oder Methoden zuzugreifen.
$thisAuf der anderen Seite wird eine Instanz und Methoden einer Klasse aufgerufen, solange auf diese Klasse zugegriffen werden kann.
Das Schlüsselwort self :: wird für die aktuelle Klasse verwendet und im Grunde genommen für den Zugriff auf statische Elemente, Methoden und Konstanten. In diesem Fall können Sie das statische Element, die Methode und die Funktionen jedoch nicht aufrufen.
Sie können das Schlüsselwort self :: in einer anderen Klasse verwenden und auf die statischen Elemente, Methoden und Konstanten zugreifen. Wann wird es von der übergeordneten Klasse erweitert und im Fall von $ dieses Schlüsselwort gleich. Sie können auf die nicht statischen Elemente, Methoden und Funktionen einer anderen Klasse zugreifen, wenn diese von der übergeordneten Klasse erweitert werden.
Der unten angegebene Code ist ein Beispiel für self :: und $ this keyword. Kopieren Sie einfach den Code und fügen Sie ihn in Ihre Codedatei ein. Die Ausgabe wird angezeigt.
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());
Antworten:
Kurze Antwort
Vollständige Antwort
Hier ist ein Beispiel für die korrekte Verwendung von
$this
undself
für nicht statische und statische Elementvariablen:Hier ist ein Beispiel für die falsche Verwendung von
$this
undself
für nicht statische und statische Elementvariablen:Hier ist ein Beispiel für Polymorphismus mit
$this
für Elementfunktionen:Hier ist ein Beispiel für die Unterdrückung des polymorphen Verhaltens mithilfe
self
von Elementfunktionen:Von http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Von http://board.phpbuilder.com/member.php?145249-laserlight
quelle
self
wird mit dem Bereichsauflösungsoperator verwendet::
, um auf die aktuelle Klasse zu verweisen. Dies kann sowohl in statischen als auch in nicht statischen Kontexten erfolgen. Darüber hinaus ist es völlig legal,$this
statische Methoden aufzurufen (aber keine Referenzfelder).$this::
?Das Schlüsselwort self bezieht sich NICHT nur auf die 'aktuelle Klasse', zumindest nicht in einer Weise, die Sie auf statische Mitglieder beschränkt.
self
Bietet im Kontext eines nicht statischen Elements auch eine Möglichkeit, die vtable ( siehe Wiki auf vtable ) für das aktuelle Objekt zu umgehen . So wie Sieparent::methodName()
die übergeordnete Version einer Funktion aufrufen können, können Sie auchself::methodName()
die aktuelle Klassenimplementierung einer Methode aufrufen.Dies wird Folgendes ausgeben:
sayHello()
Verwendet den$this
Zeiger, sodass die vtable zum Aufrufen aufgerufen wirdGeek::getTitle()
.sayGoodbye()
verwendetself::getTitle()
, daher wird die vtable nicht verwendet undPerson::getTitle()
aufgerufen. In beiden Fällen handelt es sich um die Methode eines instanziierten Objekts und wir haben Zugriff auf den$this
Zeiger innerhalb der aufgerufenen Funktionen.quelle
self
sich befindet" / "die Klassendefinition, die ein wörtlicher Teil von" ist, als auch als "die Klasse des Objekts" (was tatsächlich der Fall wärestatic
) verstanden werden kann.$this::
?$this::
; Alle möglichen Fälle werden bereits durch häufig verwendete Syntaxen abgedeckt. Je nachdem , was Sie meinen, Verwendung$this->
,self::
oderstatic::
.NICHT VERWENDEN
self::
, verwendenstatic::
Es gibt noch einen weiteren Aspekt des Selbst: der erwähnenswert ist. Ärgerlicherweise
self::
bezieht sich der Geltungsbereich zum Zeitpunkt der Definition und nicht zum Zeitpunkt der Ausführung . Betrachten Sie diese einfache Klasse mit zwei Methoden:Wenn wir anrufen, sehen
Person::status()
wir "Person lebt". Überlegen Sie nun, was passiert, wenn wir eine Klasse erstellen, die davon erbt:Beim Aufrufen wird
Deceased::status()
erwartet, dass "Person ist verstorben" angezeigt wird. Wir sehen jedoch "Person lebt", da der Bereich die ursprüngliche Methodendefinition enthält, als der Aufruf vonself::getStatus()
definiert wurde.PHP 5.3 hat eine Lösung. Der
static::
Auflösungsoperator implementiert "späte statische Bindung", was eine ausgefallene Art zu sagen ist, dass sie an den Umfang der aufgerufenen Klasse gebunden ist. Ändern Sie die Zeile instatus()
zustatic::getStatus()
, und die Ergebnisse sind das, was man erwarten würde. In älteren Versionen von PHP müssen Sie einen Kludge finden, um dies zu tun.Siehe PHP-Dokumentation
Also, um die Frage nicht wie gestellt zu beantworten ...
$this->
bezieht sich auf das aktuelle Objekt (eine Instanz einer Klasse), währendstatic::
sich auf eine Klasse beziehtquelle
getStatus
Methode als eine, die ich für eine Klasseninstanz aufrufen würde, nicht für eine Klasse.self::
, können Sie das weniger bekommen verwirrenderweise unter Verwendung des spezifischen Klassennamens, zMyClass::
. B.Um wirklich zu verstehen, worüber wir sprechen, wenn wir über
self
versus sprechen$this
, müssen wir uns tatsächlich mit dem befassen, was auf konzeptioneller und praktischer Ebene vor sich geht. Ich habe nicht das Gefühl, dass eine der Antworten dies angemessen macht. Hier ist mein Versuch.Lassen Sie uns zunächst darüber sprechen, was eine Klasse und ein Objekt sind.
Klassen und Objekte, konzeptionell
Was ist eine Klasse ? Viele Leute definieren es als Blaupause oder Vorlage für ein Objekt. In der Tat können Sie hier mehr über Klassen in PHP lesen . Und bis zu einem gewissen Grad ist es das wirklich. Schauen wir uns eine Klasse an:
Wie Sie sehen können, gibt es für diese Klasse eine Eigenschaft namens
$name
und eine Methode (Funktion)sayHello()
.Es ist sehr wichtig zu beachten, dass die Klasse eine statische Struktur ist. Dies bedeutet, dass die
Person
einmal definierte Klasse überall, wo Sie sie betrachten, immer dieselbe ist.Ein Objekt hingegen ist eine sogenannte Instanz einer Klasse. Das bedeutet, dass wir den "Entwurf" der Klasse nehmen und daraus eine dynamische Kopie erstellen. Diese Kopie ist jetzt speziell an die Variable gebunden, in der sie gespeichert ist. Daher sind alle Änderungen an einer Instanz lokal für diese Instanz.
Wir erstellen neue Instanzen einer Klasse mit dem
new
Operator.Daher sagen wir, dass eine Klasse eine globale Struktur und ein Objekt eine lokale Struktur ist. Mach dir keine Sorgen um diese lustige
->
Syntax, wir werden gleich darauf eingehen.Eine andere Sache, über die wir sprechen sollten, ist, dass wir überprüfen können , ob eine Instanz
instanceof
eine bestimmte Klasse ist:$bob instanceof Person
die einen Booleschen Wert zurückgibt, wenn die$bob
Instanz mit derPerson
Klasse oder einem untergeordneten Element von erstellt wurdePerson
.Zustand definieren
Lassen Sie uns ein wenig untersuchen, was eine Klasse tatsächlich enthält. Es gibt 5 Arten von "Dingen", die eine Klasse enthält:
Eigenschaften - Stellen Sie sich diese als Variablen vor, die jede Instanz enthalten wird.
Statische Eigenschaften - Stellen Sie sich diese als Variablen vor, die auf Klassenebene gemeinsam genutzt werden. Dies bedeutet, dass sie niemals von jeder Instanz kopiert werden.
Methoden - Dies sind Funktionen, die jede Instanz enthält (und mit Instanzen arbeitet).
Statische Methoden - Dies sind Funktionen, die von der gesamten Klasse gemeinsam genutzt werden. Sie arbeiten nicht mit Instanzen, sondern nur mit den statischen Eigenschaften.
Konstanten - Klassenaufgelöste Konstanten. Hier nicht tiefer gehen, sondern der Vollständigkeit halber hinzufügen:
Im Grunde speichern wir Informationen über den Klassen- und Objektcontainer mithilfe von "Hinweisen" zu statischen Informationen, die angeben, ob die Informationen gemeinsam genutzt werden (und daher statisch sind) oder nicht (und daher dynamisch).
Zustand und Methoden
Innerhalb einer Methode wird die Instanz eines Objekts durch die
$this
Variable dargestellt. Der aktuelle Status dieses Objekts ist vorhanden, und das Mutieren (Ändern) einer Eigenschaft führt zu einer Änderung dieser Instanz (jedoch nicht anderer).Wenn eine Methode statisch aufgerufen wird, ist die
$this
Variable nicht definiert . Dies liegt daran, dass einem statischen Aufruf keine Instanz zugeordnet ist.Das Interessante dabei ist, wie statische Anrufe getätigt werden. Sprechen wir also darüber, wie wir auf den Staat zugreifen:
Zugriffsstatus
Nachdem wir diesen Status gespeichert haben, müssen wir darauf zugreifen. Dies kann etwas knifflig werden (oder weit mehr als ein bisschen). Teilen wir dies also in zwei Gesichtspunkte auf: von außerhalb einer Instanz / Klasse (z. B. von einem normalen Funktionsaufruf oder vom globalen Bereich) und innerhalb einer Instanz / class (aus einer Methode für das Objekt).
Von außerhalb einer Instanz / Klasse
Von außerhalb einer Instanz / Klasse sind unsere Regeln recht einfach und vorhersehbar. Wir haben zwei Operatoren und jeder teilt uns sofort mit, ob es sich um eine Instanz oder eine statische Klasse handelt:
->
- Objektoperator - Dies wird immer verwendet, wenn wir auf eine Instanz zugreifen.Es ist wichtig zu beachten, dass das Aufrufen
Person->foo
keinen Sinn ergibt (daPerson
es sich um eine Klasse handelt, nicht um eine Instanz). Daher ist dies ein Analysefehler.::
- Bereichsauflösungsoperator - Wird immer verwendet, um auf eine statische Eigenschaft oder Methode der Klasse zuzugreifen.Darüber hinaus können wir eine statische Methode für ein Objekt auf dieselbe Weise aufrufen:
Es ist äußerst wichtig zu beachten, dass die Instanz des Objekts , wenn wir dies von außen tun , vor der
bar()
Methode verborgen bleibt . Das heißt, es ist genau das gleiche wie beim Laufen:Daher
$this
ist im statischen Aufruf nicht definiert.Aus dem Inneren einer Instanz / Klasse
Hier ändern sich die Dinge ein bisschen. Es werden dieselben Operatoren verwendet, aber ihre Bedeutung wird erheblich unscharf.
Der Objektoperator
->
wird weiterhin verwendet, um den Instanzstatus des Objekts aufzurufen.Das Aufrufen der
bar()
Methode für$foo
(eine Instanz vonFoo
) mit dem Objektoperator:$foo->bar()
führt zur Version von der Instanz von$a
.So erwarten wir es also.
Die Bedeutung des
::
Operators ändert sich jedoch. Dies hängt vom Kontext des Aufrufs der aktuellen Funktion ab:In einem statischen Kontext
In einem statischen Kontext sind alle mit verwendeten Anrufe
::
auch statisch. Schauen wir uns ein Beispiel an:Der Aufruf
Foo::bar()
wird der Anrufbaz()
statisch Methode, und daher$this
wird nicht aufgefüllt werden. Es ist erwähnenswert, dass dies in neueren Versionen von PHP (5.3+) einenE_STRICT
Fehler auslöst , da wir nicht statische Methoden statisch aufrufen.Innerhalb eines Instanzkontexts
In einem Instanzkontext hingegen
::
hängen Anrufe, die mit ausgeführt werden, vom Empfänger des Anrufs ab (der Methode, die wir aufrufen). Wenn die Methode definiert ist alsstatic
, wird ein statischer Aufruf verwendet. Ist dies nicht der Fall, werden die Instanzinformationen weitergeleitet.Wenn Sie sich also den obigen Code ansehen,
$foo->bar()
wird der Aufruf zurückgegebentrue
, da der "statische" Aufruf innerhalb eines Instanzkontexts erfolgt.Sinn ergeben? Das habe ich nicht gedacht. Es ist verwirrend.
Tastenkürzel
Da das Zusammenbinden von Elementen mithilfe von Klassennamen ziemlich schmutzig ist, bietet PHP drei grundlegende "Verknüpfungs" -Schlüsselwörter, um die Auflösung des Bereichs zu vereinfachen.
self
- Dies bezieht sich auf den aktuellen Klassennamen. Istself::baz()
also dasselbe wieFoo::baz()
innerhalb derFoo
Klasse (jede Methode darauf).parent
- Dies bezieht sich auf das übergeordnete Element der aktuellen Klasse.static
- Dies bezieht sich auf die aufgerufene Klasse. Dank der Vererbung können untergeordnete Klassen Methoden und statische Eigenschaften überschreiben.static
Wenn wir sie also anstelle eines Klassennamens aufrufen, können wir feststellen, woher der Anruf stammt und nicht auf der aktuellen Ebene.Beispiele
Der einfachste Weg, dies zu verstehen, besteht darin, sich einige Beispiele anzusehen. Lassen Sie uns eine Klasse auswählen:
Jetzt betrachten wir hier auch die Vererbung. Ignorieren Sie für einen Moment, dass dies ein schlechtes Objektmodell ist, aber schauen wir uns an, was passiert, wenn wir damit spielen:
Der ID-Zähler wird also von beiden Instanzen und den untergeordneten Elementen gemeinsam genutzt (da wir
self
für den Zugriff darauf verwenden. Wenn wir ihn verwendenstatic
, können wir ihn in einer untergeordneten Klasse überschreiben).Beachten Sie, dass wir die
Person::getName()
Instanzmethode jedes Mal ausführen . Aber wir verwenden dasparent::getName()
, um es in einem der Fälle zu tun (dem untergeordneten Fall). Dies macht diesen Ansatz leistungsfähig.Wort der Vorsicht # 1
Beachten Sie, dass der aufrufende Kontext bestimmt, ob eine Instanz verwendet wird. Deshalb:
Ist nicht immer wahr.
Jetzt ist es hier wirklich komisch. Wir rufen eine andere Klasse auf, aber die
$this
, die an dieFoo::isFoo()
Methode übergeben wird, ist die Instanz von$bar
.Dies kann alle möglichen Fehler und konzeptionelle WTF-Fehler verursachen. Also ich sehr empfehlen würde die Vermeidung
::
Operator aus Instanzmethoden auf irgendetwas außer den drei virtuellen „short-cut“ keywords (static
,self
, undparent
).Wort der Vorsicht # 2
Beachten Sie, dass statische Methoden und Eigenschaften von allen gemeinsam genutzt werden. Das macht sie im Grunde zu globalen Variablen. Mit den gleichen Problemen, die mit Globals kommen. Daher würde ich sehr zögern, Informationen in statischen Methoden / Eigenschaften zu speichern, es sei denn, Sie sind damit einverstanden, dass sie wirklich global sind.
Wort der Vorsicht # 3
Im Allgemeinen möchten Sie das verwenden, was als Late-Static-Binding bezeichnet wird, indem Sie
static
anstelle von verwendenself
. Beachten Sie jedoch, dass sie nicht dasselbe sind. Daher ist es sehr kurzsichtig , zu sagen, dass immer verwendenstatic
statt verwendenself
. Halten Sie stattdessen an und überlegen Sie, welchen Anruf Sie tätigen möchten, und überlegen Sie, ob untergeordnete Klassen diese statische Auflösung überschreiben können Anruf.TL / DR
Schade, geh zurück und lies es. Es mag zu lang sein, aber es ist so lang, weil dies ein komplexes Thema ist
TL / DR # 2
Ok, gut. Kurz gesagt,
self
wird verwendet , um das Bezug der aktuellen Klassennamen innerhalb einer Klasse, in der, wie$this
auf die aktuelle Objekt verweist Instanz . Beachten Sie, dass diesself
eine Verknüpfung zum Kopieren / Einfügen ist. Sie können es sicher durch Ihren Klassennamen ersetzen, und es wird gut funktionieren. Ist$this
aber eine dynamische Variable, die nicht im Voraus bestimmt werden kann (und möglicherweise nicht einmal Ihre Klasse ist).TL / DR # 3
Wenn der Objektoperator (
->
) verwendet wird, wissen Sie immer , dass es sich um eine Instanz handelt. Wenn der Scope-Resolution-Operator verwendet wird (::
), benötigen Sie weitere Informationen zum Kontext (befinden wir uns bereits in einem Objektkontext? Befinden wir uns außerhalb eines Objekts? Usw.).quelle
$this
wird nicht definiert, wenn Sie "Strikte Standards" befolgen und keine statischen Methoden aufrufen, die nicht als statisch definiert sind. Ich sehe das Ergebnis, das Sie hier erklärt haben: 3v4l.org/WeHVM Einverstanden, wirklich komisch.Foo::isFoo()
statisch genannt,$this
wird es nicht definiert. Das ist meiner Meinung nach intuitiver. - Ein anderes Ergebnis ergibt sich, wennBar
vonFoo
. DannFoo::isFoo()
würde sich der Aufruf tatsächlich im Instanzkontext befinden (nicht spezifisch für PHP7).self
(nicht $ self) bezieht sich auf die Art der Klasse, wo , wie$this
auf die aktuelle bezieht Instanz der Klasse.self
dient zur Verwendung in statischen Elementfunktionen, um Ihnen den Zugriff auf statische Elementvariablen zu ermöglichen.$this
wird in nicht statischen Elementfunktionen verwendet und verweist auf die Instanz der Klasse, für die die Elementfunktion aufgerufen wurde.Da
this
es sich um ein Objekt handelt, verwenden Sie es wie folgt:$this->member
Da
self
es sich nicht um ein Objekt handelt, handelt es sich im Grunde genommen um einen Typ, der automatisch auf die aktuelle Klasse verweist. Sie verwenden ihn wie folgt:self::member
quelle
$this->
wird verwendet, um auf eine bestimmte Instanz der Variablen (Mitgliedsvariablen) oder Methoden einer Klasse zu verweisen.$ derek ist jetzt eine bestimmte Instanz von Person. Jede Person hat einen Vor- und einen Nachnamen, aber $ derek hat einen bestimmten Vor- und Nachnamen (Derek Martin). Innerhalb der $ derek-Instanz können wir diese als $ this-> first_name und $ this-> last_name bezeichnen
ClassName :: wird verwendet, um auf diesen Klassentyp und seine statischen Variablen, statische Methoden, zu verweisen. Wenn es hilft, können Sie das Wort "statisch" mental durch "geteilt" ersetzen. Da sie gemeinsam genutzt werden, können sie nicht auf $ this verweisen, das sich auf eine bestimmte Instanz bezieht (nicht freigegeben). Statische Variablen (dh statische $ db_connection) können von allen Instanzen eines Objekttyps gemeinsam genutzt werden. Beispielsweise teilen sich alle Datenbankobjekte eine einzige Verbindung (statische $ Verbindung).
Statische Variablen Beispiel: Stellen Sie sich vor, wir haben eine Datenbankklasse mit einer einzelnen Mitgliedsvariablen: static $ num_connections; Fügen Sie dies nun in den Konstruktor ein:
So wie Objekte Konstruktoren haben, haben sie auch Destruktoren, die ausgeführt werden, wenn das Objekt stirbt oder nicht gesetzt ist:
Jedes Mal, wenn wir eine neue Instanz erstellen, wird unser Verbindungszähler um eins erhöht. Jedes Mal, wenn wir eine Instanz zerstören oder nicht mehr verwenden, wird der Verbindungszähler um eins verringert. Auf diese Weise können wir die Anzahl der Instanzen des Datenbankobjekts überwachen, mit denen wir arbeiten:
Da $ num_connections statisch (gemeinsam genutzt) ist, gibt es die Gesamtzahl der aktiven Datenbankobjekte wieder. Möglicherweise wurde diese Technik verwendet, um Datenbankverbindungen für alle Instanzen einer Datenbankklasse freizugeben. Dies geschieht, weil das Erstellen der Datenbankverbindung sehr lange dauert. Daher ist es am besten, nur eine zu erstellen und diese freizugeben (dies wird als Singleton-Muster bezeichnet).
Statische Methoden (dh öffentliche statische View :: format_phone_number ($ digits)) können verwendet werden, OHNE zuerst eines dieser Objekte zu instanziieren (dh sie verweisen nicht intern auf $ this).
Beispiel für eine statische Methode:
Wie Sie sehen können, weiß die öffentliche statische Funktion PrettyName nichts über das Objekt. Es funktioniert nur mit den Parametern, die Sie übergeben, wie eine normale Funktion, die nicht Teil eines Objekts ist. Warum also die Mühe machen, wenn wir es einfach nicht als Teil des Objekts haben könnten?
SELBST :: Wenn Sie außerhalb des Objekts codieren , das über die statische Methode verfügt, auf die Sie verweisen möchten, müssen Sie es mit dem Objektnamen View :: format_phone_number ($ phone_number) aufrufen. Wenn Sie innerhalb des Objekts codieren , das über die statische Methode verfügt, auf die Sie verweisen möchten, können Sie entweder den Objektnamen View :: format_phone_number ($ pn) oder die Verknüpfung self :: format_phone_number ($ pn) verwenden
Gleiches gilt für statische Variablen: Beispiel: View :: templates_path versus self :: templates_path
Wenn wir in der DB-Klasse auf eine statische Methode eines anderen Objekts verweisen, verwenden wir den Namen des Objekts: Beispiel: Session :: getUsersOnline ();
Wenn die DB-Klasse jedoch auf ihre eigene statische Variable verweisen möchte, sagt sie einfach self: Beispiel: self :: connection;
Hoffe das hilft Dinge aufzuklären :)
quelle
$
Zeichen verwenden müssen. Zum Beispielself::$templates_path
Aus diesem Blog-Beitrag :
quelle
In PHP verwenden Sie das Schlüsselwort self, um auf statische Eigenschaften und Methoden zuzugreifen.
Das Problem ist , dass Sie ersetzen können ,
$this->method()
mitself::method()
überall, unabhängig davon , obmethod()
statisch deklariert wird oder nicht. Welches sollten Sie also verwenden?Betrachten Sie diesen Code:
In diesem Beispiel
self::who()
wird immer 'parent' ausgegeben, während$this->who()
von der Klasse des Objekts abhängt.Jetzt können wir sehen, dass sich self auf die Klasse bezieht, in der es aufgerufen wird, während es
$this
sich auf die Klasse des aktuellen Objekts bezieht .Daher sollten Sie self nur verwenden, wenn
$this
es nicht verfügbar ist oder wenn Sie nicht zulassen möchten, dass Nachkommenklassen die aktuelle Methode überschreiben.quelle
$this
Bezieht sich innerhalb einer Klassendefinition auf das aktuelle Objekt, währendself
sich auf die aktuelle Klasse bezieht.Es ist erforderlich, mit auf ein Klassenelement zu verweisen
self
und mit auf ein Objektelement zu verweisen$this
.quelle
quelle
Laut http://www.php.net/manual/en/language.oop5.static.php gibt es keine
$self
. Es gibt nur$this
, um auf die aktuelle Instanz der Klasse (das Objekt) und self zu verweisen, die verwendet werden können, um auf statische Mitglieder einer Klasse zu verweisen. Hier kommt der Unterschied zwischen einer Objektinstanz und einer Klasse ins Spiel.quelle
Ich glaube, die Frage war nicht, ob Sie das statische Mitglied der Klasse durch Aufrufen aufrufen können
ClassName::staticMember
. Die Frage war, was der Unterschied zwischenself::classmember
und ist$this->classmember
.Zum Beispiel funktionieren beide der folgenden Beispiele fehlerfrei, unabhängig davon, ob Sie
self::
oder verwenden$this->
quelle
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
bezieht sich auf die aktuelle Klasse (in der es heißt),$this
verweist auf das aktuelle Objekt. Sie können statisch anstelle von selbst verwenden. Siehe das Beispiel:Ausgabe: Eltern Kind
quelle
$this
auf bezieht sich auf das aktuelle Objekt.static
bezieht sich auf das aktuelle Objekt.self
bezieht sich auf die genaue Klasse, in der er definiert wurde.parent
bezieht sich auf das übergeordnete Element der genauen Klasse, in der es definiert wurde.Siehe das folgende Beispiel, das die Überlastung zeigt.
Meistens möchten Sie sich auf die aktuelle Klasse beziehen, weshalb Sie
static
oder verwenden$this
. Es gibt jedoch Zeiten, in denen Sie die ursprüngliche Klasse benötigen,self
unabhängig davon, was sie erweitert. (Sehr, sehr selten)quelle
Da hier niemand über Leistungen sprach, ist hier ein kleiner Maßstab, den ich gemacht habe (5.6):
Das sind die Ergebnisse für 2 000 000 Läufe, und hier ist der Code, den ich verwendet habe:
quelle
1 / 2e9 s = 0.5 ns
diesen Tagen machtuse
Schlüsselwort tbh nicht verwendet habe, aber ich habe kein PHP mehr, um einen Benchmark zu wiederholen, und ich habe keine Lust, ihn neu zu installieren.Wenn
self
es mit dem::
Operator verwendet wird, bezieht es sich auf die aktuelle Klasse, was sowohl in statischen als auch in nicht statischen Kontexten erfolgen kann.$this
bezieht sich auf das Objekt selbst. Darüber hinaus ist es völlig legal,$this
statische Methoden aufzurufen (aber nicht auf Felder zu verweisen).quelle
Ich bin auf dieselbe Frage gestoßen und die einfache Antwort lautet:
$this
erfordert eine Instanz der Klasseself::
nichtWenn Sie statische Methoden oder statische Attribute verwenden und diese aufrufen möchten, ohne dass ein Objekt der Klasse instanziiert wurde, müssen Sie
self:
sie aufrufen, da$this
immer ein Objekt erstellt werden muss.quelle
$this
bezieht sich auf das aktuelle Klassenobjekt,self
bezieht sich auf die aktuelle Klasse (kein Objekt). Die Klasse ist die Blaupause des Objekts. Sie definieren also eine Klasse, aber Sie konstruieren Objekte.Also mit anderen Worten, verwenden Sie
self for static
undthis for none-static members or methods
.Auch im Child / Parent-Szenario
self / parent
wird meistens verwendet, um untergeordnete und übergeordnete Klassenmitglieder und -methoden zu identifizieren.quelle
Zusätzlich seit
$this::
noch nicht diskutiert.Nur zu Informationszwecken, ab PHP 5.3, wenn mit instanziierten Objekten gearbeitet wird, um den aktuellen Bereichswert zu erhalten
static::
, kann man alternativ$this::
wie folgt verwenden.http://ideone.com/7etRHy
Die Verwendung des obigen Codes ist keine übliche oder empfohlene Vorgehensweise, sondern dient lediglich der Veranschaulichung seiner Verwendung und dient eher als "Wussten Sie, dass?" in Bezug auf die Frage des Originalplakats.
Es repräsentiert auch die Verwendung von
$object::CONSTANT
zum Beispielecho $foo::NAME;
im Gegensatz zu$this::NAME;
quelle
Verwenden
self
Sie diese Option, wenn Sie eine Methode einer Klasse aufrufen möchten, ohne ein Objekt / eine Instanz dieser Klasse zu erstellen, wodurch RAM gespart wird (verwenden Sie manchmal self für diesen Zweck). Mit anderen Worten, es wird tatsächlich eine Methode statisch aufgerufen. Verwendungthis
für Objektperspektive.quelle
Fall 1: Verwenden
self
kann für Klassenkonstanten verwendet werdenWenn Sie es außerhalb der Klasse aufrufen möchten, verwenden Sie, um
classA::POUNDS_TO_KILOGRAMS
auf die Konstanten zuzugreifenFall 2: Für statische Eigenschaften
quelle
Nach php.net gibt es drei spezielle Schlüsselwörter in diesem Zusammenhang:
self
,parent
undstatic
. Sie werden verwendet, um über die Klassendefinition auf Eigenschaften oder Methoden zuzugreifen.$this
Auf der anderen Seite wird eine Instanz und Methoden einer Klasse aufgerufen, solange auf diese Klasse zugegriffen werden kann.quelle
Das Schlüsselwort self :: wird für die aktuelle Klasse verwendet und im Grunde genommen für den Zugriff auf statische Elemente, Methoden und Konstanten. In diesem Fall können Sie das statische Element, die Methode und die Funktionen jedoch nicht aufrufen.
Sie können das Schlüsselwort self :: in einer anderen Klasse verwenden und auf die statischen Elemente, Methoden und Konstanten zugreifen. Wann wird es von der übergeordneten Klasse erweitert und im Fall von $ dieses Schlüsselwort gleich. Sie können auf die nicht statischen Elemente, Methoden und Funktionen einer anderen Klasse zugreifen, wenn diese von der übergeordneten Klasse erweitert werden.
Der unten angegebene Code ist ein Beispiel für self :: und $ this keyword. Kopieren Sie einfach den Code und fügen Sie ihn in Ihre Codedatei ein. Die Ausgabe wird angezeigt.
quelle