Quelle est la différence entre :: (double colon) et -> (flèche) en PHP?


197

Il existe deux façons distinctes d'accéder aux méthodes en PHP, mais quelle est la différence?

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

et

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

Je suppose que ->(tiret avec un signe supérieur à ou un chevron) est utilisé pour les fonctions des variables et ::(deux-points) pour les fonctions des classes. Correct?

L' =>opérateur d'affectation est-il uniquement utilisé pour affecter des données dans un tableau? Est-ce en contraste avec l' =opérateur d'affectation qui est utilisé pour instancier ou modifier une variable?



Réponses:


173

Lorsque la partie gauche est une instance d'objet, vous utilisez ->. Sinon, vous utilisez ::.

Cela signifie qu'il ->est principalement utilisé pour accéder aux membres d'instance (bien qu'il puisse également être utilisé pour accéder aux membres statiques, une telle utilisation est déconseillée), tandis qu'il ::est généralement utilisé pour accéder aux membres statiques (bien que dans quelques cas spéciaux, il soit utilisé pour accéder aux membres d'instance ).

En général, ::est utilisé pour la résolution de portée , et il peut avoir soit un nom de classe, parent, selfou (en PHP 5.3) staticà sa gauche. parentfait référence à la portée de la superclasse de la classe où elle est utilisée; selffait référence à la portée de la classe où elle est utilisée; staticfait référence à la "portée appelée" (voir les liaisons statiques tardives ).

La règle est qu'un appel avec ::est un appel d'instance si et seulement si:

  • la méthode cible n'est pas déclarée comme statique et
  • il existe un contexte d'objet compatible au moment de l'appel, ce qui signifie qu'il doit être vrai:
    1. l'appel est fait à partir d'un contexte où $thisexiste et
    2. la classe de $thisest soit la classe de la méthode appelée, soit une sous-classe de celle-ci.

Exemple:

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

Production:

B :: $ prop_static: B :: $ prop_static valeur
B :: func_static (): dans B :: func_static

$ b-> prop_instance: B :: $ prop_instance valeur
$ b-> func_static (): dans B :: func_static

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

$ a-> dyn ():
dans A :: callDynamic
en dynamique dyn (__callStatic)

$ b-> dyn ():
dans A :: callDynamic
en dynamique dyn (__call)

3
" ->est principalement utilisé pour accéder aux membres de l'instance (bien qu'il puisse également être utilisé pour accéder aux membres statiques, une telle utilisation est déconseillée)" Je ne savais pas que cela pouvait l'être. Donc, s'il "fonctionne" d'une manière ou d'une autre lorsqu'il est utilisé pour accéder à des membres statiques - à quelle différence de comportement peut-on s'attendre si on ne l'utilise pas correctement comme ceci? Juste par curiosité.
lucideer

4
@lucideer Dans le cas de méthodes statiques, c'est une question de bonne pratique (la méthode appartient à la classe elle-même), mais PHP ne se plaint pas si on appelle une méthode statique avec ->. Bien sûr, vous devrez peut-être instancier la classe juste pour appeler une méthode statique, il y a donc également un impact sur les performances. Cependant, avec les propriétés, il y a plus de problèmes. Un avertissement STRICT est émis et il peut ou non fonctionner . Notez que l'inverse est également vrai - vous pouvez appeler une méthode d'instance statiquement, mais c'est encore pire (et vous ne pouvez pas l'utiliser $thisdans une telle implémentation de méthode).
Artefacto

52

::est utilisé dans un contexte statique , ie. lorsqu'une méthode ou une propriété est déclarée comme statique:

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

$result = Math::sin(123);

De plus, l' ::opérateur (l'opérateur de résolution d'étendue, alias Paamayim Nekudotayim ) est utilisé dans un contexte dynamique lorsque vous appelez une méthode / propriété d'une classe parente:

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

->est utilisé dans un contexte dynamique , ie. lorsque vous traitez une instance d'une classe:

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

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

Soit dit en passant: je ne pense pas que l'utilisation de Symfony soit une bonne idée lorsque vous n'avez aucune expérience de POO.


24

En fait, par ce symbole, nous pouvons appeler une méthode de classe qui est statique et ne dépend pas d'une autre initialisation ...

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

Ici, la doWrite()fonction ne dépend d'aucune autre méthode ou variable, et c'est une méthode statique. C'est pourquoi nous pouvons appeler cette méthode par cet opérateur sans initialiser l'objet de cette classe.

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

Mais si vous souhaitez appeler la writeméthode de cette manière, elle générera une erreur car elle dépend de l'initialisation.


16

L' =>opérateur est utilisé pour affecter des paires clé-valeur dans un tableau associatif. Par exemple:

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

Sa signification est similaire dans l' foreachénoncé:

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

14

La différence entre les méthodes et propriétés statiques et instanciées semble être l'un des plus grands obstacles à ceux qui débutent avec OOP PHP en PHP 5.

L'opérateur à deux points (appelé Paamayim Nekudotayim de l'hébreu - trivia) est utilisé lors de l'appel d'un objet ou d'une propriété à partir d'un contexte statique . Cela signifie qu'une instance de l'objet n'a pas encore été créée.

L'opérateur flèche, à l'inverse, appelle des méthodes ou des propriétés à partir d'une référence d'une instance de l'objet.

Les méthodes statiques peuvent être particulièrement utiles dans les modèles d'objets liés à une base de données pour les méthodes de création et de suppression, car vous pouvez définir la valeur de retour sur l'ID de table inséré, puis utiliser le constructeur pour instancier l'objet par l'ID de ligne.


2

Oui, je viens de frapper mon premier 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Mon mauvais, j'en avais un $instance::method()qui aurait dû l'être $instance->method(). Que je suis bête.

La chose étrange est que cela fonctionne toujours très bien sur ma machine locale (exécutant PHP 5.3.8) - rien, pas même un avertissement avec error_reporting = E_ALL - mais pas du tout sur le serveur de test, là ça explose juste avec une erreur de syntaxe et un écran blanc dans le navigateur. Étant donné que la journalisation PHP était désactivée sur la machine de test et que la société d'hébergement était trop occupée pour l'activer, ce n'était pas trop évident.

Donc, mot d'avertissement: apparemment, certaines installations PHP vous permettront d'utiliser une méthode $ instance ::, tandis que d'autres non.

Si quelqu'un peut expliquer pourquoi, veuillez le faire.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.