¿Cuál es la diferencia entre :: (doble colon) y -> (flecha) en PHP?

197

Hay dos formas distintas de acceder a los métodos en PHP, pero ¿cuál es la diferencia?

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

y

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

Supongo que ->(guión con mayor que signo o chevron) se usa para funciones para variables, y ::(dos puntos) se usa para funciones para clases. ¿Correcto?

¿El =>operador de asignación solo se usa para asignar datos dentro de una matriz? ¿Esto contrasta con el =operador de asignación que se usa para crear instancias o modificar una variable?

Joe
fuente
1
Posible duplicado de la diferencia entre los operadores de dos puntos y flechas en PHP?
Defensor orgánico el

Respuestas:

173

Cuando la parte izquierda es una instancia de objeto, se usa ->. De lo contrario, usted usa ::.

Esto significa que ->se usa principalmente para acceder a miembros de instancia (aunque también se puede usar para acceder a miembros estáticos, se desaconseja dicho uso), mientras ::que generalmente se usa para acceder a miembros estáticos (aunque en algunos casos especiales, se usa para acceder a miembros de instancia )

En general, ::se utiliza para la resolución de alcance , y puede tener ya sea un nombre de clase, parent, self, o (en PHP 5.3) statica su izquierda. parentse refiere al alcance de la superclase de la clase donde se usa; selfse refiere al alcance de la clase donde se usa; staticse refiere al "alcance llamado" (ver enlaces estáticos tardíos ).

La regla es que una llamada con ::es una llamada de instancia si y solo si:

  • el método de destino no se declara como estático y
  • hay un contexto de objeto compatible en el momento de la llamada, lo que significa que estos deben ser verdaderos:
    1. la llamada se realiza desde un contexto donde $thisexiste y
    2. la clase de $thises la clase del método que se llama o una subclase del mismo.

Ejemplo:

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

Salida:

B :: $ prop_static: B :: $ prop_static valor
B :: func_static (): en B :: func_static

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

$ b-> func_instance ():
en B :: instancia_función
en A :: instancia_función
en A :: instancia_función

$ a-> dyn ():
en A :: callDynamic
en dyn dinámico (__callStatic)

$ b-> dyn ():
en A :: callDynamic
en dyn dinámico (__call)
Artefacto
fuente
3
" ->se usa principalmente para acceder a miembros de la instancia (aunque también se puede usar para acceder a miembros estáticos, se desaconseja dicho uso)" No sabía que podría serlo. Entonces, si "funciona" de alguna manera cuando se usa para acceder a miembros estáticos, ¿qué diferencia de comportamiento se esperaría si se usara incorrectamente de esta manera? Solo por curiosidad.
lucideer
44
@lucideer En el caso de los métodos estáticos, es una cuestión de buena práctica (el método pertenece a la clase en sí), pero PHP no se queja si llama a un método estático con ->. Por supuesto, es posible que deba crear una instancia de la clase solo para llamar a un método estático, por lo que también hay un impacto en el rendimiento. Con las propiedades, sin embargo, hay más problemas. Se genera una advertencia ESTRICTA y puede o no funcionar . Tenga en cuenta que lo contrario también es cierto: puede llamar a un método de instancia estáticamente, pero esto es aún peor (y no puede usarlo $thisen la implementación de dicho método).
Artefacto
52

::se usa en contexto estático , es decir. cuando algún método o propiedad se declara como estático:

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

$result = Math::sin(123);

Además, el ::operador (el Operador de resolución de alcance, también conocido como Paamayim Nekudotayim ) se usa en contexto dinámico cuando invoca un método / propiedad de una clase principal:

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

->se utiliza en contexto dinámico , es decir. cuando tratas con alguna instancia de alguna clase:

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

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

Por cierto: no creo que usar Symfony sea una buena idea cuando no tienes experiencia en OOP.

Crozin
fuente
24

En realidad, con este símbolo podemos llamar a un método de clase que es estático y no depende de otra inicialización ...

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

Aquí la doWrite()función no depende de ningún otro método o variable, y es un método estático. Es por eso que podemos llamar a este método por este operador sin inicializar el objeto de esta clase.

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

Pero si desea llamar al writemétodo de esta manera, generará un error porque depende de la inicialización.

Mrinmoy Ghoshal
fuente
16

El =>operador se utiliza para asignar pares clave-valor en una matriz asociativa. Por ejemplo:

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

Su significado es similar en la foreachdeclaración:

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

La diferencia entre los métodos y propiedades estáticos e instanciados parece ser uno de los mayores obstáculos para aquellos que recién comienzan con OOP PHP en PHP 5.

El operador de dos puntos (que se llama Paamayim Nekudotayim del hebreo - trivia) se usa cuando se llama a un objeto o propiedad desde un contexto estático . Esto significa que todavía no se ha creado una instancia del objeto.

El operador de flecha, por el contrario, llama a métodos o propiedades que a partir de una referencia de una instancia del objeto.

Los métodos estáticos pueden ser especialmente útiles en modelos de objetos que están vinculados a una base de datos para crear y eliminar métodos, ya que puede establecer el valor de retorno en la ID de la tabla insertada y luego usar el constructor para crear una instancia del objeto por la ID de la fila.

DiáconoDesperado
fuente
2

Sí, acabo de golpear mi primero 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Mi mal, tuve un $instance::method()que debería haber sido $instance->method(). Tonto de mí.

Lo extraño es que esto todavía funciona bien en mi máquina local (ejecutando PHP 5.3.8), nada, ni siquiera una advertencia con error_reporting = E_ALL, pero nada en el servidor de prueba, simplemente explota con un error de sintaxis y una pantalla blanca en el navegador. Como el registro de PHP estaba desactivado en la máquina de prueba, y la empresa de hosting estaba demasiado ocupada para activarlo, no era demasiado obvio.

Entonces, una advertencia: aparentemente, algunas instalaciones de PHP le permitirán usar un $ instance :: method (), mientras que otros no.

Si alguien puede explicar por qué es eso, por favor hágalo.

PapaFreud
fuente