用双冒号(::)调用非静态方法

为什么我不能使用静态方法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警告。 支持静态调用非静态方法将来可能会被删除。

链接