Qual è la differenza tra :: (doppio punto) e -> (freccia) in PHP?


197

Esistono due modi distinti per accedere ai metodi in PHP, ma qual è la differenza?

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

e

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

Suppongo che ->(trattino con maggiore di segno o chevron) sia usato per funzioni per variabili e ::(doppio punto) sia usato per funzioni per classi. Corretta?

L' =>operatore di assegnazione viene utilizzato solo per assegnare dati all'interno di un array? Ciò è in contrasto con l' =operatore di assegnazione utilizzato per creare un'istanza o modificare una variabile?



Risposte:


173

Quando la parte sinistra è un'istanza di oggetto, si utilizza ->. Altrimenti, usi ::.

Ciò significa che ->viene utilizzato principalmente per accedere ai membri dell'istanza (sebbene possa anche essere utilizzato per accedere ai membri statici, tale utilizzo è sconsigliato), mentre di ::solito viene utilizzato per accedere ai membri statici (sebbene in alcuni casi speciali, venga utilizzato per accedere ai membri dell'istanza ).

In generale, ::è utilizzato per la risoluzione ambito , e può avere sia un nome di classe, parent, self, o (in PHP 5.3) staticalla sua sinistra. parentsi riferisce all'ambito della superclasse della classe in cui viene utilizzata; selfsi riferisce all'ambito della classe in cui viene utilizzato; staticsi riferisce al "campo di applicazione chiamato" (vedere i collegamenti statici tardivi ).

La regola è che una chiamata con ::è una chiamata di istanza se e solo se:

  • il metodo target non è dichiarato come statico e
  • esiste un contesto oggetto compatibile al momento della chiamata, nel senso che devono essere veri:
    1. la chiamata viene effettuata da un contesto in cui $thisesiste e
    2. la classe di $thisè la classe del metodo chiamato o una sua sottoclasse.

Esempio:

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

Produzione:

B :: $ prop_static: B :: $ valore prop_static
B :: func_static (): in B :: func_static

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

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

$ A-> din ():
in A :: callDynamic
in dyn dinamico (__callStatic)

$ B-> din ():
in A :: callDynamic
in dyn dinamico (__call)

3
" ->viene utilizzato principalmente per accedere ai membri dell'istanza (sebbene possa essere utilizzato anche per accedere ai membri statici, tale utilizzo è sconsigliato)" Non sapevo che potesse esserlo. Quindi, se "funziona" in qualche modo se usato per accedere a membri statici - quale differenza di comportamento ci si aspetterebbe se si utilizzasse in modo errato in questo modo? Solo per curiosità.
Lucideer,

4
@lucideer Nel caso di metodi statici, è una questione di buone pratiche (il metodo appartiene alla classe stessa), ma PHP non si lamenta se chiama un metodo statico con ->. Naturalmente, potrebbe essere necessario creare un'istanza della classe solo per chiamare un metodo statico, quindi c'è anche un impatto sulle prestazioni. Con le proprietà, tuttavia, ci sono più problemi. Viene generato un avviso STRICT che potrebbe o meno funzionare . Si noti che è vero anche il contrario: è possibile chiamare staticamente un metodo di istanza, ma è anche peggio (e non è possibile utilizzarlo $thisin tale implementazione del metodo).
Artefacto,

52

::viene utilizzato in un contesto statico , ad es. quando alcuni metodi o proprietà sono dichiarati come statici:

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

$result = Math::sin(123);

Inoltre, l' ::operatore (Scope Resolution Operator, alias Paamayim Nekudotayim ) viene utilizzato in un contesto dinamico quando si richiama un metodo / proprietà di una classe genitore:

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

->viene utilizzato in un contesto dinamico , ad es. quando hai a che fare con qualche istanza di qualche classe:

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

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

A proposito: non penso che usare Symfony sia una buona idea quando non hai alcuna esperienza OOP.


24

In realtà con questo simbolo possiamo chiamare un metodo di classe che è statico e non dipende da altre inizializzazioni ...

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

Qui la doWrite()funzione non dipende da nessun altro metodo o variabile ed è un metodo statico. Ecco perché possiamo chiamare questo metodo da questo operatore senza inizializzare l'oggetto di questa classe.

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

Ma se si desidera chiamare il writemetodo in questo modo, verrà generato un errore perché dipende dall'inizializzazione.


16

L' =>operatore viene utilizzato per assegnare coppie chiave-valore in un array associativo. Per esempio:

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

Il suo significato è simile foreachnell'affermazione:

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

14

La differenza tra metodi e proprietà statici e istanziati sembra essere uno dei maggiori ostacoli a quelli che hanno appena iniziato con OOP PHP in PHP 5.

L'operatore double colon (che si chiama Paamayim Nekudotayim dall'ebraico - curiosità) viene utilizzato quando si chiama un oggetto o una proprietà da un oggetto statico contesto . Ciò significa che un'istanza dell'oggetto non è stata ancora creata.

L'operatore freccia, al contrario, chiama metodi o proprietà che da un riferimento a un'istanza dell'oggetto.

I metodi statici possono essere particolarmente utili nei modelli di oggetti collegati a un database per i metodi di creazione ed eliminazione, poiché è possibile impostare il valore restituito sull'ID tabella inserito e quindi utilizzare il costruttore per creare un'istanza dell'oggetto tramite l'id riga.


2

Sì, ho appena colpito il mio primo 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Mio male, avevo un $instance::method()che avrebbe dovuto essere $instance->method(). Sciocco me

La cosa strana è che questo funziona ancora bene sul mio computer locale (eseguendo PHP 5.3.8) - niente, nemmeno un avvertimento con error_reporting = E_ALL - ma non è affatto sul server di test, lì esplode solo con un errore di sintassi e uno schermo bianco nel browser. Dato che la registrazione PHP era disattivata sulla macchina di prova e la società di hosting era troppo impegnata per accenderla, non era troppo ovvio.

Quindi, avvertimento: apparentemente, alcune installazioni di PHP ti permetteranno di usare un $ instance :: method (), mentre altri no.

Se qualcuno può espandersi sul perché, per favore, fallo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.