用双冒号(::)调用非静态方法
为什么我不能使用静态方法static(class :: method)的非静态方法? 这是一些configuration问题?
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非常松散。 有一件事我没有看到这里注意到,如果你调用一个非静态的方法,静态地从类C
的非静态方法内ns
$this
里面ns
将引用你的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
如果你有严格的错误报告,这实际上是某种错误,但不是。
这是PHP的一个已知的“怪癖”。 这是devise来防止反向传播,以找出是否前一段时间我们实际上实例化一个对象(请记住,PHP解释,而不是编译)。 但是,如果对象没有实例化,访问任何非静态成员通过范围parsing运算符将发出致命错误。
由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 ?>
PHP 4没有静态关键字(在函数声明上下文中),但仍然允许使用::
静态调用方法。 为了向后兼容的目的,这继续在PHP 5中。
这是PHP 4的向后兼容性。 在PHP 4中,对象方法和作为静态类方法编写的全局函数之间无法区别。 所以两者都有效。
但是,随着PHP 5中的对象模型的变化 – http://php.net/oop5-引入了static关键字。;
然后,从PHP 5.1.3开始,您将获得适当的严格标准警告,例如:
严格标准:非静态方法Foo :: bar()不应被静态调用
和/或:
严格标准:非静态方法Foo :: bar()不应该静态调用,假设$ this来自不兼容的上下文
您应该已经启用了您的开发设置。 所以这只是向后兼容的时候,语言不能有足够的差异,所以这是在运行时“定义”。
现在你可以在代码中定义它,但是如果你仍然把它称为“错误的”,代码将不会被破坏。
一些演示触发错误消息,并显示改变了不同的PHP版本的行为:http: //3v4l.org/8WRQH
你可以这样做,但是如果你在函数fun1()
使用$this
this,你的代码将会出错。
在大多数语言中,您将需要有一个类的实例来执行实例方法。 看起来,当您使用范围parsing运算符调用实例方法时,PHP将创build一个临时实例。
不知道为什么PHP允许这样做,但你不想养成这样做的习惯。 你的例子只工作,因为它不尝试访问类的非静态属性。
一些简单的事情:
<?php class Foo { private $color; public function bar() { echo 'before'; $this->color = "blue"; echo 'after'; } } Foo::bar();
会导致一个致命的错误
我注意到,如果从一个类中调用非静态方法self :: test(),则不会发出严格标准的警告,如调用Class :: test()时。 我相信这和LSB没有关系,因为我的课没有扩展(在php 5.5上testing过)?
警告在PHP 7中,静态调用非静态方法已被废弃,并将生成E_DEPRECATED警告。 支持静态调用非静态方法将来可能会被删除。
链接