Llamar a un método no estático con dos puntos (::)
¿Por qué no puedo utilizar un método no estático con la sintaxis de los métodos static(class::method) ? ¿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
el interior 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
En realidad, esto es un error de algún tipo si tiene un informe de errores estricto, pero no en caso contrario.
Esta es una "peculiaridad" conocida de PHP. Está diseñado para evitar la propagación hacia atrás para determinar si hace algún tiempo realmente creamos una instancia de un objeto o no (recuerde, PHP se interpreta, no se compila). Sin embargo, acceder a cualquier miembro no estático mediante el operador de resolución de alcance si no se crea una instancia del objeto generará 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 . "</br>"; // yields nothing
//echo $object1->GIVE . "</br>"; // deliberately misnamed, still yields nothing
//echo $object1->User::GIVEN . "</br>"; // yields nothing
//echo $object1->a . "</br>"; // yields 2
//echo $object1->b . "</br>"; // yields nothing
//echo $object1->me() . "</br>"; // yields print me
//echo $object1->you() . "</br>"; // 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 . "</br>"; // yields nothing
//echo $object2->a . "</br>"; // yields 2
//echo $object2->b . "</br>"; // yields nothing
//echo $object2->me() . "</br>"; // yields print me
//echo $object2->you() . "</br>"; // yields print you
// Are the properties and methods accessible directly in the class?
//echo User::GIVEN . "</br>"; // yields 1
//echo User::$a . "</br>"; // yields fatal error since it is not static
//echo User::$b . "</br>"; // yields 3
//echo User::me() . "</br>"; // yields print me
//echo User::you() . "</br>"; // yields print you
// Are the properties and methods copied to the child class and are they accessible?
//echo myUser::GIVEN . "</br>"; // yields 1
//echo myUser::$a . "</br>"; // yields fatal error since it is not static
//echo myUser::$b . "</br>"; // yields 3
//echo myUser::me() . "</br>"; // yields print me
//echo myUser::you() . "</br>"; // yields print you
?>
Esta es la compatibilidad con versiones anteriores de PHP 4. En PHP 4 no se podía diferenciar 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 introdujo la palabra clave estática.
Y luego, desde PHP 5.1.3, obtienes advertencias estándar estrictas y adecuadas sobre temas como:
Estándares estrictos: el método no estático Foo::bar() no debe llamarse estáticamente
Y/O:
Estándares estrictos: el método no estático Foo::bar() no debe llamarse estáticamente, suponiendo que $this proviene de un contexto incompatible
que debería haber habilitado para su configuración de desarrollo. Por lo tanto, es simplemente compatibilidad con versiones anteriores de una época en la que el lenguaje no podía diferir lo suficiente, por lo que esto se "definió" en tiempo de ejecución.
Hoy en día ya puedes definirlo en el código, sin embargo, el código no se romperá si aún lo llamas "incorrecto".
Algunas demostraciones para activar los mensajes de error y mostrar el comportamiento modificado en diferentes versiones de PHP: http://3v4l.org/8WRQH
Puede hacer esto, pero su código generará un error si usa $this
la función llamadafun1()
Advertencia En PHP 7, llamar estáticamente a métodos no estáticos está en desuso y generará una advertencia E_DEPRECATED. Es posible que en el futuro se elimine la compatibilidad con la llamada estática a métodos no estáticos.
Enlace