it-swarm.com.de

Wann benutzt man self über $ this?

Was ist in PHP 5 der Unterschied zwischen der Verwendung von self und $this?

Wann ist jeweils angebracht?

1924
Casey Watson

Kurze Antwort

Verwenden Sie $this, um auf das aktuelle Objekt zu verweisen. Verwenden Sie self, um auf die aktuelle Klasse zu verweisen. Mit anderen Worten, verwenden Sie $this->member für nicht statische Elemente und self::$member für statische Elemente.

Volle Antwort

Hier ist ein Beispiel für korrekt ​​die Verwendung von $this und self für nicht statische und statische Elementvariablen:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

Hier ist ein Beispiel für inkorrekt ​​die Verwendung von $this und self für nicht statische und statische Elementvariablen:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

Hier ist ein Beispiel für Polymorphismus mit $this fü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 nterdrücken des polymorphen Verhaltens mit self für 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 Member-Funktion foo() für den genauen Typ des aktuellen Objekts aufruft. Wenn das Objekt type X ist, ruft es X::foo() auf. Wenn das Objekt type Y ist, ruft es Y::foo() auf. Aber mit self :: foo () wird X::foo() immer aufgerufen.

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

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

1644
John Millikin

Das Schlüsselwort self bezieht sich NOT nur auf die 'aktuelle Klasse', zumindest nicht in einer Weise, die Sie auf statische Mitglieder beschränkt. Im Kontext eines nicht statischen Members bietet self auch die Möglichkeit, die vtable ( siehe Wiki zu vtable ) für das aktuelle Objekt zu umgehen. So wie Sie mit parent::methodName() die übergeordnete Version einer Funktion aufrufen können, können Sie mit self::methodName() die aktuelle Klassenimplementierung einer Methode aufrufen.

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

Dies wird Folgendes ausgeben:

Hallo ich bin ludwig der aussenseiter
Auf Wiedersehen von Ludwig der Person

sayHello() verwendet den Zeiger $this, sodass die vtable aufgerufen wird, um Geek::getTitle() aufzurufen. sayGoodbye() verwendet self::getTitle(), daher wird die vtable nicht verwendet, und Person::getTitle() wird aufgerufen. In beiden Fällen haben wir es mit der Methode eines instanziierten Objekts zu tun und haben Zugriff auf den Zeiger $this innerhalb der aufgerufenen Funktionen.

733
nbeagle

BENUTZEN SIE NICHT _self::_, verwenden Sie _static::_

Es gibt einen weiteren Aspekt von self ::, der erwähnenswert ist. Ärgerlicherweise bezieht sich _self::_ auf den Geltungsbereich am Definitionspunkt und nicht auf den Ausführungspunkt . Betrachten Sie diese einfache Klasse mit zwei Methoden:

_class Person
{

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

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

}
_

Wenn wir Person::status() aufrufen, sehen wir "Person lebt". Überlegen Sie nun, was passiert, wenn wir eine Klasse erstellen, die davon erbt:

_class Deceased extends Person
{

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

}
_

Wenn Sie Deceased::status() aufrufen, wird erwartet, dass "Person ist verstorben" angezeigt wird. Wir sehen jedoch, dass "Person lebt", da der Gültigkeitsbereich 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 eine "späte statische Bindung". Ändern Sie die Zeile in status() in static::getStatus(), und das Ergebnis entspricht Ihren Erwartungen. In älteren Versionen von PHP müssen Sie einen Kludge finden, um dies zu tun.

Siehe PHP-Dokumentation

Also, um die Frage nicht so zu beantworten, wie sie gestellt wurde ...

_$this->_ verweist auf das aktuelle Objekt (eine Instanz einer Klasse), während _static::_ auf eine Klasse verweist

449
Sqoo

Um wirklich zu verstehen, wovon wir reden, wenn wir über self versus $this sprechen, müssen wir uns tatsächlich damit befassen, was auf konzeptioneller und praktischer Ebene vor sich geht. Ich habe nicht das Gefühl, dass eine der Antworten dies angemessen macht. Deshalb hier mein Versuch.

Lassen Sie uns zunächst darüber sprechen, was eine Klasse und eine Objekt ist.

Klassen und Objekte, konzeptionell

Also, was ist ​​a class ? Viele Leute definieren es als Blaupause oder Vorlage für ein Objekt. In der Tat können Sie mehr lesen Über Klassen in PHP hier . Und bis zu einem gewissen Grad ist es das, was es wirklich ist. Schauen wir uns eine Klasse an:

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

Wie Sie sehen können, gibt es eine Eigenschaft für diese Klasse mit dem Namen $name und eine Methode (Funktion) mit dem Namen sayHello().

Es ist sehr wichtig zu beachten, dass die Klasse eine statische Struktur ist. Dies bedeutet, dass die einmal definierte Klasse Person immer dieselbe ist, wenn Sie sie ansehen.

Ein Objekt hingegen ist das, was als - Instanz einer Klasse bezeichnet wird. Das bedeutet, dass wir die "Blaupause" 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 = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

Wir erstellen neue Instanzen einer Klasse mit dem Operator new.

Daher sagen wir, dass eine Klasse eine globale Struktur und ein Objekt eine lokale Struktur ist. Mach dir keine Sorgen über diese lustige -> -Syntax, wir werden uns gleich damit befassen.

Eine andere Sache, über die wir sprechen sollten, ist, dass wir check können, wenn eine Instanz eine instanceof eine bestimmte Klasse ist: $bob instanceof Person, die einen Booleschen Wert zurückgibt, wenn der Die Instanz $bob wurde mit der Klasse Person erstellt, oder einem untergeordneten Element von Person.

Zustand definieren

Lassen Sie uns ein wenig darüber nachdenken, was eine Klasse tatsächlich enthält. Es gibt 5 Arten von "Dingen", die eine Klasse enthält:

  1. Properties - Betrachten Sie diese als Variablen, die jede Instanz enthalten wird.

    class Foo {
        public $bar = 1;
    }
    
  2. Static Properties - Stellen Sie sich diese Variablen als Variablen vor, die auf Klassenebene gemeinsam genutzt werden. Das bedeutet, dass sie niemals von jeder Instanz kopiert werden.

    class Foo {
        public static $bar = 1;
    }
    
  3. Methoden - Dies sind Funktionen, die jede Instanz enthält (und auf Instanzen angewendet wird).

    class Foo {
        public function bar() {}
    }
    
  4. Static Methods - Dies sind Funktionen, die von der gesamten Klasse verwendet werden. Sie arbeiten nicht ​​mit Instanzen, sondern nur mit den statischen Eigenschaften.

    class Foo {
        public static function bar() {}
    }
    
  5. Konstanten - Klassenaufgelöste Konstanten. Ich gehe hier nicht tiefer, sondern füge der Vollständigkeit halber hinzu:

    class Foo {
        const BAR = 1;
    }
    

Im Grunde genommen speichern wir also Informationen über den Klassen- und Objektcontainer mithilfe von "Hinweisen" über static , die angeben, ob die Informationen gemeinsam genutzt werden (und daher statisch sind) oder nicht (und daher dynamisch sind) ).

Zustand und Methoden

Innerhalb einer Methode wird die Instanz eines Objekts durch die Variable $this dargestellt. Der aktuelle Status dieses Objekts ist vorhanden, und das Mutieren (Ändern) einer Eigenschaft führt zu einer Änderung an dieser Instanz (jedoch nicht an anderen).

Wenn eine Methode statisch aufgerufen wird, ist die $this -Variable ist nicht definiert . Dies liegt daran, dass mit einem statischen Aufruf keine Instanz verknüpft 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 way mehr als ein bisschen), also teilen wir dies in zwei Gesichtspunkte auf: von außerhalb einer Instanz/Klasse (z. B. von einem normalen Funktionsaufruf oder aus dem globalen Bereich) ) und innerhalb einer Instanz/Klasse (innerhalb einer Methode des Objekts).

Von außerhalb einer Instanz/Klasse

Außerhalb einer Instanz/Klasse sind unsere Regeln recht einfach und vorhersehbar. Wir haben zwei Operatoren, die uns sofort mitteilen, ob es sich um eine Instanz oder eine Klassenstatik handelt:

  • -> - object-operator - Wird immer verwendet, wenn wir auf eine Instanz zugreifen.

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

    Es ist wichtig zu beachten, dass das Aufrufen von Person->foo keinen Sinn ergibt (da Person eine Klasse und keine Instanz ist). Daher ist das ein Analysefehler.

  • :: - scope-resolution-operator - Dies wird immer verwendet, um auf eine statische Eigenschaft oder Methode der Klasse zuzugreifen.

    echo Foo::bar()
    

    Zusätzlich können wir auf die gleiche Weise eine statische Methode für ein Objekt aufrufen:

    echo $foo::bar()
    

    Es ist extrem wichtig zu beachten, dass wenn wir dies tun von außen, die Instanz des Objekts vor der Methode bar() verborgen wird. Das heißt, es ist genau dasselbe wie Laufen:

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

Daher ist $this im statischen Aufruf nicht definiert.

Aus dem Inneren einer Instanz/Klasse

Hier ändert sich etwas. Die gleichen Operatoren werden verwendet, aber ihre Bedeutung wird deutlich unscharf.

Der Objekt-Operator -> wird weiterhin verwendet, um den Instanzstatus des Objekts aufzurufen.

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

Das Aufrufen der Methode bar() für $foo (eine Instanz von Foo) unter Verwendung des Objektoperators: $foo->bar() führt zur Instanzversion 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

    Innerhalb eines statischen Kontexts sind alle Aufrufe, die mit :: getätigt werden, ebenfalls statisch. Schauen wir uns ein Beispiel an:

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

    Wenn Sie Foo::bar() aufrufen, wird die baz() -Methode statisch aufgerufen, und daher wird $thisnicht ​​ausgefüllt. Es ist erwähnenswert, dass dies in neueren Versionen von PHP (5.3+) einen E_STRICT -Fehler auslöst, da nicht statische Methoden statisch aufgerufen werden.

  • Innerhalb eines Instanzkontexts

    In einem Instanzkontext hingegen hängen Anrufe mit :: vom Empfänger des Anrufs ab (der Methode, die wir aufrufen). Wenn die Methode als static definiert ist, wird ein statischer Aufruf verwendet. Ist dies nicht der Fall, werden die Instanzinformationen weitergeleitet.

    Wenn Sie also den obigen Code betrachten und $foo->bar() aufrufen, wird true zurückgegeben, da der "statische" Aufruf innerhalb eines Instanzkontexts erfolgt.

Sinn ergeben? Dachte nicht so. Es ist verwirrend.

Abkürzungsschlüsselwörter

Da es ziemlich schmutzig ist, alles mit Klassennamen zusammenzubinden, bietet PHP drei grundlegende "Shortcut" -Schlüsselwörter, um die Bereichsauflösung zu vereinfachen.

  • self - Dies bezieht sich auf den aktuellen Klassennamen. Also ist self::baz() dasselbe wie Foo::baz() innerhalb der Foo -Klasse (jede Methode dafür).

  • 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. Wenn Sie sie also mit static anstelle eines Klassennamens aufrufen, können Sie feststellen, woher der Anruf kam, und nicht mit der aktuellen Ebene.

Beispiele

Der einfachste Weg, dies zu verstehen, besteht darin, sich einige Beispiele anzuschauen. Lass uns eine Klasse auswählen:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

Jetzt beschäftigen wir uns auch hier mit der Vererbung. Ignorieren Sie für einen Moment, dass dies ein schlechtes Objektmodell ist, aber schauen wir uns an, was passiert, wenn wir damit spielen:

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

Daher wird der ID-Zähler von beiden Instanzen und den untergeordneten Instanzen gemeinsam genutzt (da wir self verwenden, um darauf zuzugreifen. Wenn wir static verwenden, 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 jedes Mal die Methode Person::getName() instance ausführen. Wir verwenden jedoch die Funktion parent::getName(), um dies in einem der Fälle (dem untergeordneten Fall) zu tun. Dies macht diesen Ansatz leistungsfähig.

Wort der Vorsicht # 1

Beachten Sie, dass der aufrufende Kontext bestimmt, ob eine Instanz verwendet wird. Deshalb:

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

Ist nicht immer wahr.

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

Jetzt ist es wirklich komisch hier. Wir rufen eine andere Klasse auf, aber der $this, der an die Foo::isFoo() -Methode übergeben wird, ist die Instanz von $bar.

Dies kann alle möglichen Fehler und konzeptionelle WTF-Fehler verursachen. Daher würde ich dringend empfehlen, den Operator :: innerhalb der Instanzmethoden für alles außer diesen drei virtuellen "Shortcut" -Stichwörtern (static, self und parent) zu vermeiden. .

Wort der Vorsicht # 2

Beachten Sie, dass statische Methoden und Eigenschaften von allen gemeinsam genutzt werden. Das macht sie grundsätzlich zu globalen Variablen. Mit den gleichen Problemen, die mit Globals kommen. Ich würde also sehr zögern, Informationen in statischen Methoden/Eigenschaften zu speichern, es sei denn, Sie wissen, dass sie wirklich global sind.

Wort der Vorsicht # 3

Im Allgemeinen sollten Sie das so genannte Late-Static-Binding verwenden, indem Sie static anstelle von self verwenden. Beachten Sie jedoch, dass sie nicht dasselbe sind. Wenn Sie also sagen, dass "immer static anstelle von self verwenden", ist dies sehr kurzsichtig untergeordnete Klassen, um diesen statisch aufgelösten Aufruf überschreiben zu können.

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 den aktuellen Klassennamen innerhalb einer Klasse zu referenzieren, wobei $this auf das aktuelle Objekt ) verweist Instanz . Beachten Sie, dass self eine Verknüpfung zum Kopieren/Einfügen ist. Sie können es sicher durch Ihren Klassennamen ersetzen, und es wird gut funktionieren. Aber $this ist 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 (->), dann 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 Objekt-Kontext? Befinden wir uns außerhalb eines Objekts? Usw.).

241
ircmaxell

self (nicht $ self) bezieht sich auf das Typ der Klasse, wobei $this auf das aktuelle Instanz der Klasse verweist. self wird in statischen Elementfunktionen verwendet, um den Zugriff auf statische Elementvariablen zu ermöglichen. $this wird in nicht statischen Memberfunktionen verwendet und ist ein Verweis auf die Instanz der Klasse, in der die Memberfunktion aufgerufen wurde.

Da this ein Objekt ist, verwenden Sie es wie folgt: $this->member

Da self kein Objekt ist, ist es im Grunde ein Typ, der automatisch auf die aktuelle Klasse verweist. Sie verwenden ihn wie folgt: self::member

115
MrZebra

$this-> wird verwendet, um auf eine bestimmte Instanz der Variablen (Membervariablen) oder Methoden einer Klasse zu verweisen.

Example: 
$derek = new Person();

$ derek ist jetzt eine bestimmte Instanz von Person. Jede Person hat einen Vor- und Nachnamen, aber $ derek hat einen bestimmten Vor- und Nachnamen (Derek Martin). In der $ derek-Instanz können wir auf diese als $ this-> first_name und $ this-> last_name verweisen

ClassName :: wird verwendet, um auf diesen Klassentyp und seine statischen Variablen, die statischen 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 (nicht gemeinsam genutzte) Instanz bezieht. Statische Variablen (d. H. Static $ db_connection) können von allen Instanzen eines Objekttyps gemeinsam genutzt werden. Beispielsweise teilen sich alle Datenbankobjekte eine einzelne Verbindung (statische $ -Verbindung).

Beispiel für statische Variablen: Angenommen, wir haben eine Datenbankklasse mit einer einzelnen Mitgliedsvariablen: static $ num_connections; Fügen Sie nun Folgendes 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 der 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 an. Möglicherweise haben Sie diese Technik verwendet, um Datenbankverbindungen für alle Instanzen einer Datenbankklasse freizugeben. Dies geschieht, weil das Herstellen der Datenbankverbindung viel Zeit in Anspruch nimmt. Daher empfiehlt es sich, nur eine Datenbankverbindung zu erstellen und gemeinsam zu nutzen (dies wird als Singleton-Muster bezeichnet).

Statische Methoden (d. H. Public static View :: format_phone_number ($ digits)) können verwendet werden, OHNE eines dieser Objekte zuerst zu instanziieren (d. H. Sie verweisen intern nicht auf $ this).

Statisches Methodenbeispiel:

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

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

Wie Sie sehen, 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 sich dann die Mühe machen, wenn wir es einfach nicht als Teil des Objekts haben könnten?

  1. Erstens hilft Ihnen das Anhängen von Funktionen an Objekte, die Dinge organisiert zu halten, damit Sie wissen, wo Sie sie finden.
  2. Zweitens werden Namenskonflikte vermieden. In einem großen Projekt müssen wahrscheinlich zwei Entwickler getName () -Funktionen erstellen. Wenn einer einen ClassName1 :: getName () erstellt und der andere ClassName2 :: getName (), ist das überhaupt kein Problem. Kein Konflikt. Yay statische Methoden!

SELF :: Wenn Sie outside das Objekt mit der statischen Methode codieren, 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 mit der statischen Methode codieren, auf die Sie verweisen möchten, können Sie entweder den Namen des Objekts verwenden. View :: format_phone_number ($ pn), OR Sie können 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 ();

Aber wenn die DB-Klasse auf ihre eigene statische Variable verweisen wollte, würde sie einfach self sagen: Beispiel: self :: connection;

Hoffe, das hilft, die Dinge aufzuklären :)

96
lo_fye

Von dieser Blog-Beitrag :

  • self bezieht sich auf die aktuelle Klasse
  • self kann verwendet werden, um statische Funktionen aufzurufen und statische Elementvariablen zu referenzieren
  • self kann in statischen Funktionen verwendet werden
  • self kann auch polymorphes Verhalten deaktivieren, indem die vtable umgangen wird
  • $this bezieht sich auf das aktuelle Objekt
  • $this kann zum Aufrufen statischer Funktionen verwendet werden
  • $this sollte nicht zum Aufrufen statischer Membervariablen verwendet werden. Verwenden Sie stattdessen self.
  • $this kann nicht in statischen Funktionen verwendet werden
29
okconfused

In PHP verwenden Sie das Schlüsselwort self, um auf statische Eigenschaften und Methoden zuzugreifen.

Das Problem ist, dass Sie $this->method() überall durch self::method() ersetzen können, unabhängig davon, ob method() als statisch deklariert ist oder nicht. Also welches solltest du verwenden?

Betrachten Sie diesen Code:

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

In diesem Beispiel gibt self::who() immer "parent" aus, während $this->who() von der Klasse des Objekts abhängt.

Jetzt können wir sehen, dass self auf die Klasse verweist, in der es aufgerufen wird, während $this auf die Klasse des aktuellen Objekts verweist.

Verwenden Sie self daher nur, wenn $this nicht verfügbar ist oder wenn Sie nicht zulassen möchten, dass abgeleitete Klassen die aktuelle Methode überschreiben.

25
ramin rostami

In einer Klassendefinition bezieht sich $ this auf das aktuelle Objekt, während self auf die aktuelle Klasse verweist.

Es ist notwendig, mit self auf ein Klassenelement und mit $ this auf ein Objektelement zu verweisen.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
21
Tarun Singhal

Hier ist ein Beispiel für die korrekte Verwendung von $ this und self für nicht statische und statische Membervariablen:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?> 
20
Mohit Bumb

Laut http://www.php.net/manual/en/language.oop5.static.php gibt es keinen $self. Es gibt nur $this, um auf die aktuelle Instanz der Klasse (das Objekt) zu verweisen, und self, um auf statische Member einer Klasse zu verweisen. Hier kommt der Unterschied zwischen einer Objektinstanz und einer Klasse ins Spiel.

20
cruizer

self verweist auf die aktuelle Klasse (in der sie aufgerufen wird),

$this verweist auf das aktuelle Objekt. Sie können statisch statt selbst verwenden. Siehe das Beispiel:

    class ParentClass {
            function test() {
                    self::which();  // output 'parent'
                    $this->which(); // output 'child'
            }

            function which() {
                    echo 'parent';
            }
    }

    class ChildClass extends ParentClass {
            function which() {
                    echo 'child';
            }
    }

    $obj = new ChildClass();
    $obj->test();

Ausgabe: Eltern-Kind

15
Kabir Hossain

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.

Beispielsweise funktionieren beide folgenden Beispiele fehlerfrei, unabhängig davon, ob Sie self:: oder $this-> verwenden.

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}
14
dr evil

Da hier niemand über Performances sprach, ist hier ein kleiner Benchmark, den ich gemacht habe (5.6):

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

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 = new Tleb\Benchmark\Benchmark(2000000);

class Foo
{
    public function calling_this()
    {
        $this->called();
    }

    public function calling_self()
    {
        self::called();
    }

    public function calling_static()
    {
        static::called();
    }

    public static function called()
    {
    }
}

$b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

$b->run();
14
tleb
  • Der Objektzeiger $ this to verweist auf das aktuelle Objekt.
  • Der Klassenwert "static" bezieht sich auf das aktuelle Objekt.
  • Der Klassenwert "self" bezieht sich auf die genaue Klasse, in der er definiert wurde.
  • Der Klassenwert "parent" bezieht sich auf das übergeordnete Element der genauen Klasse, in der es definiert wurde.

Das folgende Beispiel zeigt eine Überlastung.

<?php

class A {

    public static function newStaticClass()
    {
        return new static;
    }

    public static function newSelfClass()
    {
        return new self;
    }

    public function newThisClass()
    {
        return new $this;
    }
}

class B extends A
{
    public function newParentClass()
    {
        return new parent;
    }
}


$b = new B;

var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A


class C extends B
{
    public static function newSelfClass()
    {
        return new self;
    }
}


$c = new C;

var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"

Meistens möchten Sie sich auf die aktuelle Klasse beziehen, weshalb Sie static oder $this verwenden. Es gibt jedoch Zeiten, in denen Sie benötigenself, weil Sie die ursprüngliche Klasse unabhängig von der Erweiterung möchten. (Sehr, sehr selten)

14
Xeoncross

Wenn self mit dem Operator :: verwendet wird, bezieht sich dies auf die aktuelle Klasse, was sowohl in statischen als auch in nicht statischen Kontexten möglich ist. $this bezieht sich auf das Objekt selbst. Darüber hinaus ist es völlig legal, $this zu verwenden, um statische Methoden aufzurufen (aber nicht auf Felder zu verweisen).

13
mrDjouk

$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, konstruieren aber Objekte.

Verwenden Sie also mit anderen Worten self for static und this for none-static members or methods.

auch im Kind/Eltern-Szenario wird self / parent hauptsächlich verwendet, um die Mitglieder und Methoden der Kind- und Elternklasse zu identifizieren.

7
Rakesh Singh

Außerdem wurde seit $this:: noch nicht diskutiert.

Nur zu Informationszwecken kann ab PHP 5.3, wenn mit instanziierten Objekten gearbeitet wird, um den aktuellen Bereichswert zu erhalten, im Gegensatz zur Verwendung von static:: auch $this:: wie folgt verwendet werden.

http://ideone.com/7etRHy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

Die Verwendung des obigen Codes ist keine übliche oder empfohlene Vorgehensweise, sondern dient lediglich der Veranschaulichung seiner Verwendung und soll eher als "Wussten Sie schon?" in Bezug auf die Frage des ursprünglichen Posters.

Es repräsentiert auch die Verwendung von $object::CONSTANT zum Beispiel echo $foo::NAME; im Gegensatz zu $this::NAME;

7
fyrye

Ich bin auf dieselbe Frage gestoßen und die einfache Antwort lautet:

  • $ this benötigt eine Instanz der Klasse
  • self :: nicht

Wann immer Sie statische Methoden oder statische Attribute verwenden und sie aufrufen möchten, ohne ein Objekt der Klasse instanziiert zu haben, müssen Sie self :: verwenden um sie aufzurufen, weil $ this immer erfordert, dass ein Objekt erstellt wird.

6
Mike

Verwenden Sie self, wenn Sie eine Methode einer Klasse aufrufen möchten, ohne ein Objekt/eine Instanz dieser Klasse zu erstellen. Speichern Sie also RAM (verwenden Sie manchmal self für diesen Zweck). Mit anderen Worten, es ruft tatsächlich eine Methode statisch auf. Verwenden Sie this für die Objektperspektive.

5
minhajul

Fall 1: Use self kann für Klassenkonstanten verwendet werden

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

Wenn Sie es außerhalb der Klasse aufrufen möchten, verwenden Sie classA::POUNDS_TO_KILOGRAMS, um auf die Konstanten zuzugreifen

Fall 2: Für statische Eigenschaften

 class classC {
 public function __construct () {
 self :: $ _ counter ++; $ this-> num = self :: $ _ counter; 
} 
} 
2
li bing zhao

Laut php.net gibt es in diesem Zusammenhang drei spezielle Schlüsselwörter: self, parent und static. Sie werden verwendet, um innerhalb der Klassendefinition auf Eigenschaften oder Methoden zuzugreifen.

$this hingegen wird verwendet, um eine Instanz und Methoden einer Klasse aufzurufen, solange auf diese Klasse zugegriffen werden kann.

1
Fil