llamar a un método estático dentro de una clase?

166

¿Cómo llamo a un método estático desde otro método dentro de la misma clase?

$this->staticMethod();

o

$this::staticMethod();
ajsie
fuente
13
Quizás te interese esto ( selfvs. $this): stackoverflow.com/questions/151969/php-self-vs-this
Felix Kling
Solo para su información, su primer ejemplo es una variable de instancia que llama a un método estático que no es posible porque un método estático es parte de la clase y no es accesible a través de una variable de instancia.
joejoeson
puede eliminar $ this ahora, por favor, no funciona si solo usa métodos estáticos y no existe una instancia.
malhal

Respuestas:

322
self::staticMethod();

Más información sobre la palabra clave estática.

jeroen
fuente
...¿pero por qué? $ this-> staticMethod () también funciona. ¿Puedes explicar por qué self :: staticMethod () es más correcto (si lo es)?
Ian Dunn
29
@Ian Dunn En pocas palabras, $thissolo existe si se ha instanciado un objeto y solo se puede usar $this->methoddesde un objeto existente. Si no tiene ningún objeto pero solo llama a un método estático y en ese método desea llamar a otro método estático en la misma clase, debe usarlo self::. Por lo tanto, para evitar posibles errores (y advertencias estrictas) es mejor usarlo self.
jeroen
1
¡Gracias! En laravel, descubrí que accidentalmente estaba llamando al método estático a través de un controlador extendido usando $this, pero el problema no surgió hasta que se introdujo el código stage. no volvieron errores, el valor era justo 0. tenga cuidado con esto, useself::
blamb
44

Asumamos que esta es tu clase:

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

    public static function staticMethod() { echo "static method\n"; }
}

Desde dentro del foo()método, veamos las diferentes opciones:

$this->staticMethod();

Entonces eso llama staticMethod()como un método de instancia, ¿verdad? No es asi. Esto se debe a que el método se declara ya que public staticel intérprete lo llamará como método estático, por lo que funcionará como se esperaba. Podría argumentarse que al hacerlo, resulta menos obvio del código que se está realizando una llamada al método estático.

$this::staticMethod();

Desde PHP 5.3 puede usar $var::method()para significar <class-of-$var>::; Esto es bastante conveniente, aunque el caso de uso anterior todavía es poco convencional. Eso nos lleva a la forma más común de llamar a un método estático:

self::staticMethod();

Ahora, antes de comenzar a pensar que ::es el operador de llamada estática, déjame darte otro ejemplo:

self::bar();

Esto imprimirá baz = 1, lo que significa eso $this->bar()y self::bar()hará exactamente lo mismo; eso es porque ::es solo un operador de resolución de alcance. Es ahí para hacer parent::, self::y static::el trabajo y dará acceso a las variables estáticas; cómo se llama a un método depende de su firma y cómo se llamó a la persona que llama.

Para ver todo esto en acción, vea este resultado de 3v4l.org .

Jack
fuente
self::bar()parece engañoso, ¿está ahora en desuso? (utilizando self::para llamar a un método de instancia en lugar de un método estático).
ToolmakerSteve
@ToolmakerSteve, ¿de qué manera dirías que es engañoso?
Ja͢ck
Lógicamente hablando, no existe selfcuando se invoca un método estático. Por definición: el método estático se puede llamar desde cualquier lugar y no recibe un parámetro "propio". Sin embargo, veo la conveniencia de esa phpsintaxis, para que no tenga que escribir MyClassName::. Estoy acostumbrado a los lenguajes de tipo estático, donde el compilador tiene que recibir todas las variables disponibles en el ámbito actual, por lo que (el equivalente de) self::puede omitirse. Entonces uno solo dijo self instanceMethod; No hay razón para decir self staticMethod.
ToolmakerSteve
15

Esta es una respuesta muy tardía, pero agrega algunos detalles sobre las respuestas anteriores.

Cuando se trata de llamar a métodos estáticos en PHP desde otro método estático en la misma clase, es importante diferenciar entre selfy el nombre de la clase.

Tome por ejemplo este código:

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

La salida de este código es:

Clase original

Clase extendida

Esto se debe a que se selfrefiere a la clase en la que se encuentra el código, en lugar de la clase del código desde el que se llama.

Si desea usar un método definido en una clase que hereda la clase original, debe usar algo como:

$class = get_called_class();
$class::function_name(); 
Joundill
fuente
2
Encontré esto informativo. Una pequeña mentira, no diría que las otras respuestas son "engañosas". Más exacto decir que están "incompletos"; no abordan la pregunta (no formulada) de qué self::sucede en el caso (raro) en el que un método estático A llama a otro método estático B, y B ha sido anulado en una subclase. En mi humilde opinión, es menos confuso restringir la anulación de métodos a métodos de "instancia"; usa esa habilidad con moderación en el nivel estático. Dicho de otra manera, los lectores de su código esperan que el método sobrescriba los métodos de instancia (esa es la esencia de la codificación OO), pero no los estáticos.
ToolmakerSteve
1
Muy útil y tiene sentido que una extensión de la clase no sea la clase original. Por lo tanto, es lógico pensar que selfno se utilizaría en ese caso. Has declarado una clase separada como una extensión de la primera clase. Usar selfdentro de la clase extendida se referiría a la clase extendida. Esto no contradice las otras respuestas, pero ciertamente ayuda a demostrar el alcance de self.
iyrin
2

En la versión posterior de PHP self::staticMethod();tampoco funcionará. Lanzará el estricto error estándar.

En este caso, podemos crear objetos de la misma clase y llamar por objeto

aquí está el ejemplo

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}
Nishad Up
fuente
Usted podría hacer eso, aunque si fun1no se está haciendo uso de self, no es lógico que sea un método de instancia. La forma correcta de hacer esto en php es declarar public static function fun1, a continuación, llamar mediante la especificación de la clase: Foo::fun1. Estoy seguro de que esa es la forma prevista para corregir ese error estándar estricto.
ToolmakerSteve