Was ist der Unterschied zwischen :: (Doppelpunkt) und -> (Pfeil) in PHP?


196

Es gibt zwei verschiedene Möglichkeiten, auf Methoden in PHP zuzugreifen, aber was ist der Unterschied?

$response->setParameter('foo', 'bar');

und

sfConfig::set('foo', 'bar');

Ich gehe davon aus, dass ->(Bindestrich mit mehr als Vorzeichen oder Chevron) für Funktionen für Variablen und ::(Doppelpunkt) für Funktionen für Klassen verwendet wird. Richtig?

Wird der =>Zuweisungsoperator nur zum Zuweisen von Daten innerhalb eines Arrays verwendet? Steht dies im Gegensatz zu dem =Zuweisungsoperator, mit dem eine Variable instanziiert oder geändert wird?



Antworten:


172

Wenn der linke Teil eine Objektinstanz ist, verwenden Sie ->. Ansonsten verwenden Sie ::.

Dies bedeutet, dass dies ->hauptsächlich für den Zugriff auf Instanzmitglieder verwendet wird (obwohl es auch für den Zugriff auf statische Mitglieder verwendet werden kann, von einer solchen Verwendung wird abgeraten), während ::es normalerweise für den Zugriff auf statische Mitglieder verwendet wird (obwohl es in einigen besonderen Fällen für den Zugriff auf Instanzmitglieder verwendet wird ).

Im Allgemeinen ::wird für verwendet Umfang Auflösung , und es kann entweder ein Klassennamen haben, parent, self, oder (in PHP 5.3) staticauf seiner linken Seite. parentbezieht sich auf den Umfang der Oberklasse der Klasse, in der sie verwendet wird; selfbezieht sich auf den Umfang der Klasse, in der sie verwendet wird; staticbezieht sich auf den "aufgerufenen Bereich" (siehe späte statische Bindungen ).

Die Regel ist, dass ein Aufruf mit ::genau dann ein Instanzaufruf ist, wenn:

  • Die Zielmethode ist nicht als statisch und deklariert
  • Zum Zeitpunkt des Aufrufs gibt es einen kompatiblen Objektkontext. Dies bedeutet, dass diese zutreffen müssen:
    1. Der Aufruf erfolgt aus einem Kontext, in dem $thisvorhanden ist und
    2. Die Klasse von $thisist entweder die Klasse der aufgerufenen Methode oder eine Unterklasse davon.

Beispiel:

class A {
    public function func_instance() {
        echo "in ", __METHOD__, "\n";
    }
    public function callDynamic() {
        echo "in ", __METHOD__, "\n";
        B::dyn();
    }

}

class B extends A {
    public static $prop_static = 'B::$prop_static value';
    public $prop_instance = 'B::$prop_instance value';

    public function func_instance() {
        echo "in ", __METHOD__, "\n";
        /* this is one exception where :: is required to access an
         * instance member.
         * The super implementation of func_instance is being
         * accessed here */
        parent::func_instance();
        A::func_instance(); //same as the statement above
    }

    public static function func_static() {
        echo "in ", __METHOD__, "\n";
    }

    public function __call($name, $arguments) {
        echo "in dynamic $name (__call)", "\n";
    }

    public static function __callStatic($name, $arguments) {
        echo "in dynamic $name (__callStatic)", "\n";
    }

}

echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";

echo '$b->func_instance():', "\n", $b->func_instance(), "\n";

/* This is more tricky
 * in the first case, a static call is made because $this is an
 * instance of A, so B::dyn() is a method of an incompatible class
 */
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
 * instance of B (despite the fact we are in a method of A), so
 * B::dyn() is a method of a compatible class (namely, it's the
 * same class as the object's)
 */
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";

Ausgabe:

B :: $ prop_static: B :: $ prop_static-Wert
B :: func_static (): in B :: func_static

$ b-> prop_instance: B :: $ prop_instance-Wert
$ b-> func_static (): in B :: func_static

$ b-> func_instance ():
in B :: func_instance
in A :: func_instance
in A :: func_instance

$ a-> dyn ():
in A :: callDynamic
in dynamischem Dyn (__callStatic)

$ b-> dyn ():
in A :: callDynamic
in dynamischem Dyn (__call)

3
" ->wird hauptsächlich für den Zugriff auf Instanzmitglieder verwendet (obwohl es auch für den Zugriff auf statische Mitglieder verwendet werden kann, wird von einer solchen Verwendung abgeraten)" Ich wusste nicht, dass dies möglich ist. Wenn es also beim Zugriff auf statische Elemente auf irgendeine Weise "funktioniert" - welchen Unterschied im Verhalten würde man erwarten, wenn man es so falsch verwendet? Nur aus Neugier.
Lucideer

4
@lucideer Bei statischen Methoden handelt es sich um eine bewährte Methode (die Methode gehört zur Klasse selbst), aber PHP beschwert sich nicht, wenn eine statische Methode mit aufgerufen wird ->. Natürlich müssen Sie möglicherweise die Klasse instanziieren, um eine statische Methode aufzurufen. Daher gibt es auch einen Leistungseinbruch. Bei Eigenschaften gibt es jedoch weitere Probleme. Eine STRICT-Warnung wird ausgelöst und funktioniert möglicherweise oder nicht . Beachten Sie, dass auch das Gegenteil der Fall ist - Sie können eine Instanzmethode statisch aufrufen, dies ist jedoch noch schlimmer (und Sie können sie $thisin einer solchen Methodenimplementierung nicht verwenden ).
Artefacto

52

::wird im statischen Kontext verwendet, dh. Wenn eine Methode oder Eigenschaft als statisch deklariert ist:

class Math {
    public static function sin($angle) {
        return ...;
    }
}

$result = Math::sin(123);

Außerdem wird der ::Operator (der Scope Resolution Operator, auch bekannt als Paamayim Nekudotayim ) im dynamischen Kontext verwendet, wenn Sie eine Methode / Eigenschaft einer übergeordneten Klasse aufrufen:

class Rectangle {
     protected $x, $y;

     public function __construct($x, $y) {
         $this->x = $x;
         $this->y = $y;
     }
}

class Square extends Rectangle {
    public function __construct($x) {
        parent::__construct($x, $x);
    }
}

->wird im dynamischen Kontext verwendet, dh. Wenn Sie sich mit einer Instanz einer Klasse befassen:

class Hello {
    public function say() {
       echo 'hello!';
    }
}

$h = new Hello();
$h->say();

Übrigens: Ich denke nicht, dass die Verwendung von Symfony eine gute Idee ist, wenn Sie keine OOP-Erfahrung haben.


24

Tatsächlich können wir mit diesem Symbol eine Klassenmethode aufrufen, die statisch ist und nicht von anderen Initialisierungen abhängig ist ...

class Test {

    public $name;

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

    public static function doWrite($name) {
        print 'Hello '.$name;
    }

    public function write() {
        print $this->name;
    }
}

Hier ist die doWrite()Funktion von keiner anderen Methode oder Variablen abhängig und es handelt sich um eine statische Methode. Deshalb können wir diese Methode von diesem Operator aufrufen, ohne das Objekt dieser Klasse zu initialisieren.

Test::doWrite('Mrinmoy'); // Output: Hello Mrinmoy.

Wenn Sie die writeMethode jedoch auf diese Weise aufrufen möchten , wird ein Fehler generiert, da er von der Initialisierung abhängt.


15

Der =>Operator wird verwendet, um Schlüssel-Wert-Paare in einem assoziativen Array zuzuweisen. Beispielsweise:

$fruits = array(
  'Apple'  => 'Red',
  'Banana' => 'Yellow'
);

Die Bedeutung ist in der foreachAussage ähnlich :

foreach ($fruits as $fruit => $color)
  echo "$fruit is $color in color.";

14

Der Unterschied zwischen statischen und instanziierten Methoden und Eigenschaften scheint eines der größten Hindernisse für diejenigen zu sein, die gerade erst mit OOP PHP in PHP 5 beginnen.

Der Doppelpunktoperator (auf Hebräisch Paamayim Nekudotayim genannt - Trivia) wird verwendet, wenn ein Objekt oder eine Eigenschaft aus einem statischen Kontext aufgerufen wird . Dies bedeutet, dass eine Instanz des Objekts noch nicht erstellt wurde.

Der Pfeiloperator ruft umgekehrt Methoden oder Eigenschaften auf, die aus einer Referenz einer Instanz des Objekts stammen.

Statische Methoden können besonders in Objektmodellen nützlich sein, die zum Erstellen und Löschen von Methoden mit einer Datenbank verknüpft sind, da Sie den Rückgabewert auf die eingefügte Tabellen-ID setzen und dann das Konstruktor verwenden können, um das Objekt anhand der Zeilen-ID zu instanziieren.


2

Ja, ich habe gerade meinen ersten Treffer erzielt 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Mein schlechtes, ich hatte ein $instance::method()das hätte sein sollen $instance->method(). Wie dumm von mir.

Das Seltsame ist, dass dies auf meinem lokalen Computer (mit PHP 5.3.8) immer noch einwandfrei funktioniert - nichts, nicht einmal eine Warnung mit error_reporting = E_ALL - aber überhaupt nicht auf dem Testserver, da es nur mit einem Syntaxfehler explodiert und ein weißer Bildschirm im Browser. Da die PHP-Protokollierung auf dem Testcomputer deaktiviert war und das Hosting-Unternehmen zu beschäftigt war, um sie einzuschalten, war dies nicht allzu offensichtlich.

Ein Wort der Warnung: Anscheinend können Sie bei einigen PHP-Installationen eine $ instance :: method () verwenden, bei anderen nicht.

Wenn jemand erläutern kann, warum das so ist, tun Sie dies bitte.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.