Llamando al método no estático con doble punto (: :)

¿Por qué no puedo usar un método no estático con la syntax de los métodos estáticos (clase :: método)? ¿Es algún tipo de problema de configuración?

class Teste { public function fun1() { echo 'fun1'; } public static function fun2() { echo "static fun2" ; } } Teste::fun1(); // why? Teste::fun2(); //ok - is a static method 

PHP es muy flexible con métodos estáticos y no estáticos. Una cosa que no veo aquí es que si llamas a un método no estático, ns estáticamente desde dentro de un método no estático de clase C , $this inside ns se referirá a tu instancia de C

 class A { public function test() { echo $this->name; } } class C { public function q() { $this->name = 'hello'; A::test(); } } $c = new C; $c->q();// prints hello 

Esto es en realidad un error de algún tipo si tiene un informe de error estricto, pero no de otra manera.

Esta es una “peculiaridad” conocida de PHP. Es por diseño para evitar la propagación inversa para averiguar si hace algún tiempo realizamos una instancia de un objeto o no (recuerde, PHP se interpreta, no se comstack). Sin embargo, el acceso a cualquier miembro no estático del operador de resolución de scope mediante el scope si el objeto no se crea una instancia emitirá un error fatal.

Cortesía de PHP.net:

 class User { const GIVEN = 1; // class constants can't be labeled static nor assigned visibility public $a=2; public static $b=3; public function me(){ echo "print me"; } public static function you() { echo "print you"; } } class myUser extends User { } // Are properties and methods instantiated to an object of a class, & are they accessible? //$object1= new User(); // uncomment this line with each of the following lines individually //echo $object1->GIVEN . ""; // yields nothing //echo $object1->GIVE . ""; // deliberately misnamed, still yields nothing //echo $object1->User::GIVEN . ""; // yields nothing //echo $object1->a . ""; // yields 2 //echo $object1->b . ""; // yields nothing //echo $object1->me() . ""; // yields print me //echo $object1->you() . ""; // yields print you // Are properties and methods instantiated to an object of a child class, & are accessible? //$object2= new myUser(); // uncomment this line with each of the following lines individually //echo $object2->GIVEN . ""; // yields nothing //echo $object2->a . ""; // yields 2 //echo $object2->b . ""; // yields nothing //echo $object2->me() . ""; // yields print me //echo $object2->you() . ""; // yields print you // Are the properties and methods accessible directly in the class? //echo User::GIVEN . ""; // yields 1 //echo User::$a . ""; // yields fatal error since it is not static //echo User::$b . ""; // yields 3 //echo User::me() . ""; // yields print me //echo User::you() . ""; // yields print you // Are the properties and methods copied to the child class and are they accessible? //echo myUser::GIVEN . ""; // yields 1 //echo myUser::$a . ""; // yields fatal error since it is not static //echo myUser::$b . ""; // yields 3 //echo myUser::me() . ""; // yields print me //echo myUser::you() . ""; // yields print you ?> 

PHP 4 no tenía una palabra clave estática (en el contexto de statement de función) pero aún permitía que los métodos se llamaran estáticamente con :: . Esto continuó en PHP 5 para fines de compatibilidad con versiones anteriores.

Esto es compatibilidad hacia atrás PHP 4. En PHP 4, no podría diferir entre un método de objeto y la función global escrita como un método de clase estática. Por lo tanto, ambos funcionaron.

Sin embargo, con los cambios en el modelo de objetos con PHP 5 – http://php.net/oop5 – se ha introducido la palabra clave estática.

Y luego, desde PHP 5.1.3, obtienes advertencias estándar estrictas adecuadas sobre aquellos como:

Estándares estrictos: Método no estático Foo :: bar () no debe llamarse estáticamente

Y / O:

Estándares estrictos: Método no estático Foo :: bar () no debe llamarse estáticamente, suponiendo $ this desde un contexto incompatible

que deberías haber habilitado para tu configuración de desarrollo. Por lo tanto, es meramente compatible con versiones anteriores a un momento en el que el idioma no podía ser lo suficientemente diferente, por lo que se “definió” en tiempo de ejecución.

Hoy en día puedes definirlo ya en el código, sin embargo, el código no se romperá si aún lo llamas “incorrecto”.

Algunos demo para activar los mensajes de error y mostrar el comportamiento modificado en diferentes versiones de PHP: http://3v4l.org/8WRQH

Puedes hacer esto, pero tu código tendrá un error si usas $this en la función llamada fun1()

En la mayoría de los idiomas necesitará tener una instancia de la clase para realizar métodos de instancia. Parece que PHP creará una instancia temporal cuando llame a un método de instancia con el operador de resolución de scope.

No estoy seguro de por qué PHP permite esto, pero no desea adquirir el hábito de hacerlo. Su ejemplo solo funciona porque no intenta acceder a las propiedades no estáticas de la clase.

Algo tan simple como:

 < ?php class Foo { private $color; public function bar() { echo 'before'; $this->color = "blue"; echo 'after'; } } Foo::bar(); 

daría lugar a un error fatal

Me he dado cuenta de que si llama al método no estático self :: test () desde dentro de una clase, no se emitirá ninguna advertencia para un estándar estricto, como cuando llama a Class :: test (). Creo que esto no está relacionado con LSB, ya que mi clase no se extendió (probado en php 5.5)?

Advertencia En PHP 7, la llamada a métodos no estáticos de forma estática está en desuso, y generará una advertencia E_DEPRECATED. El soporte para llamar a métodos no estáticos estáticamente puede eliminarse en el futuro.

Enlazar