Jaka jest różnica między :: (podwójny dwukropek) i -> (strzałka) w PHP?


197

Istnieją dwa różne sposoby dostępu do metod w PHP, ale jaka jest różnica?

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

i

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

Zakładam, że ->(kreska większa niż znak lub szewron) jest używana dla funkcji zmiennych, a ::(podwójne dwukropki) jest używana dla funkcji dla klas. Poprawny?

Czy =>operator przypisania służy tylko do przypisywania danych w obrębie tablicy? Czy jest to sprzeczne z =operatorem przypisania, który jest używany do tworzenia lub modyfikowania zmiennej?



Odpowiedzi:


173

Gdy lewa część jest instancją obiektu, używasz ->. W przeciwnym razie korzystasz ::.

Oznacza to, że ->jest najczęściej używany do uzyskiwania dostępu do członków instancji (chociaż może być również używany do uzyskiwania dostępu do członków statycznych, takie użycie jest odradzane), podczas gdy ::zwykle jest używany do uzyskiwania dostępu do członków statycznych (chociaż w kilku szczególnych przypadkach jest używany do uzyskiwania dostępu do członków instancji ).

Na ogół ::stosuje się do uchwały zakres i może mieć albo nazwą klasy parent, selflub (w PHP 5.3) staticz jego lewej strony. parentodnosi się do zakresu nadklasy klasy, w której jest używana; selfodnosi się do zakresu klasy, w której jest używany; staticodnosi się do „wywoływanego zakresu” (patrz późne wiązania statyczne ).

Zasadą jest, że połączenie z ::jest wywołaniem instancji wtedy i tylko wtedy, gdy:

  • metoda docelowa nie jest zadeklarowana jako statyczna i
  • w chwili wywołania istnieje zgodny kontekst obiektowy, co oznacza, że ​​muszą być prawdziwe:
    1. połączenie jest wykonywane z kontekstu, w którym $thisistnieje i
    2. klasa $thisjest albo klasą wywoływanej metody, albo jej podklasą.

Przykład:

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";

Wynik:

B :: $ prop_static: B :: $ prop_static wartość
B :: func_static (): w B :: func_static

$ b-> prop_instance: B :: $ prop_instance wartość
$ b-> func_static (): w B :: func_static

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

$ a-> dyn ():
w A :: callDynamic
w dynamicznym dyn (__callStatic)

$ b-> dyn ():
w A :: callDynamic
w dynamicznym dyn (__call)

3
->służy głównie do uzyskiwania dostępu do członków instancji (chociaż może być również używany do uzyskiwania dostępu do członków statycznych, takie użycie jest odradzane)” „Nie wiedziałem, że może być. Więc jeśli „funkcjonuje” w jakiś sposób, gdy jest używany do uzyskiwania dostępu do elementów statycznych - jakiej różnicy w zachowaniu można się spodziewać, jeśli użyjemy go w ten sposób nieprawidłowo? Z czystej ciekawości.
lucideer,

4
@lucideer W przypadku metod statycznych jest to kwestia dobrych praktyk (metoda należy do samej klasy), ale PHP nie narzeka, jeśli wywoła metodę statyczną ->. Oczywiście może zaistnieć potrzeba utworzenia instancji klasy tylko w celu wywołania metody statycznej, więc jest też uderzenie wydajności. Jednak w przypadku właściwości jest więcej problemów. Pojawia się ostrzeżenie STRICT, które może działać lub nie . Zauważ, że odwrotność jest również prawdą - możesz wywołać metodę instancji statycznie, ale jest to jeszcze gorsze (i nie możesz użyć $thisw implementacji takiej metody).
Artefacto,

52

::jest używany w kontekście statycznym , tj. gdy jakaś metoda lub właściwość jest zadeklarowana jako statyczna:

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

$result = Math::sin(123);

Ponadto ::operator (operator rozpoznawania zakresu , znany również jako Paamayim Nekudotayim ) jest używany w kontekście dynamicznym podczas wywoływania metody / właściwości klasy nadrzędnej:

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);
    }
}

->jest używany w kontekście dynamicznym , tj. kiedy masz do czynienia z jakąś instancją jakiejś klasy:

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

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

Nawiasem mówiąc: nie sądzę, że używanie Symfony jest dobrym pomysłem, jeśli nie masz doświadczenia w OOP.


24

Właściwie za pomocą tego symbolu możemy wywołać metodę klasy, która jest statyczna i nie może być zależna od innej inicjalizacji ...

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;
    }
}

Tutaj doWrite()funkcja nie jest zależna od żadnej innej metody lub zmiennej i jest to metoda statyczna. Dlatego możemy wywołać tę metodę przez ten operator bez inicjowania obiektu tej klasy.

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

Ale jeśli chcesz wywołać writemetodę w ten sposób, wygeneruje błąd, ponieważ jest ona zależna od inicjalizacji.


16

=>Operatora jest stosowane par klucz wartość przeniesienia na tablicy asocjacyjnej. Na przykład:

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

Jego znaczenie jest podobne w foreachstwierdzeniu:

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

14

Różnica między metodami statycznymi a instancjami i właściwościami wydaje się być jedną z największych przeszkód dla osób rozpoczynających pracę z OOP PHP w PHP 5.

Operator podwójnego dwukropka (zwany hebrajskim Paamayim Nekudotayim - ciekawostki) jest używany podczas wywoływania obiektu lub właściwości z kontekstu statycznego . Oznacza to, że instancja obiektu nie została jeszcze utworzona.

I odwrotnie, operator strzałki wywołuje metody lub właściwości, które pochodzą z odwołania do instancji obiektu.

Metody statyczne mogą być szczególnie przydatne w modelach obiektów połączonych z bazą danych w celu tworzenia i usuwania metod, ponieważ można ustawić wartość zwracaną dla wstawionego identyfikatora tabeli, a następnie użyć konstruktora, aby utworzyć instancję obiektu według identyfikatora wiersza.


2

Tak, właśnie uderzyłem pierwszy 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Mój zły, miałem taki, $instance::method()który powinien być $instance->method(). Głupi ja.

Dziwne jest to, że to nadal działa dobrze na mojej lokalnej maszynie (działającej w PHP 5.3.8) - nic, nawet ostrzeżenie z raportowaniem błędów = E_ALL - ale wcale nie działa na serwerze testowym, tam po prostu eksploduje z błędem składni i biały ekran w przeglądarce. Ponieważ rejestrowanie PHP zostało wyłączone na maszynie testowej, a firma hostingowa była zbyt zajęta, aby ją włączyć, nie było to zbyt oczywiste.

Zatem słowo ostrzeżenia: najwyraźniej niektóre instalacje PHP pozwolą ci użyć $ instance :: method (), podczas gdy inne nie.

Jeśli ktoś może wyjaśnić, dlaczego tak jest, proszę.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.