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
,那么ns
内部的$this
将指向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的已知“怪癖”。这是出于设计考虑,以防止回溯,以确定一段时间前是否实例化了对象(请记住,PHP是解释性语言,而非编译语言)。但是,如果未实例化对象,则通过作用域解析运算符访问任何非静态成员将发出致命错误。
Courtesy of 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 4 中,无法区分作为静态类方法编写的全局函数和对象方法。因此两者都可以使用。
然而,随着 PHP 5 中对象模型的变化-http://php.net/oop5 - 引入了 static 关键字。
自从 PHP 5.1.3 以来,您会得到有关这些问题的适当严格警告:
Strict Standards: Non-static method Foo::bar() should not be called statically
和/或:
Strict Standards: Non-static method Foo::bar() should not be called statically, assuming $this from incompatible context
您应该在开发环境中启用它们。所以这只是向后兼容到一个语言不能够足够区分的时间,因此这是在运行时“定义”的。
现在,您已经可以在代码中定义它,但如果仍然“错误”调用它,代码也不会出现错误。
一些演示用于触发错误消息并显示不同 PHP 版本下的不同行为:http://3v4l.org/8WRQH
在PHP 4中,没有静态关键字(在函数声明上下文中),但仍允许使用::
静态调用方法。出于向后兼容性的目的,这种做法在PHP 5中得以延续。
您可以这样做,但是如果在调用fun1()
函数时使用$this
,则会出现错误。
警告:在PHP 7中,静态地调用非静态方法已经被弃用,并且会产生一个E_DEPRECATED警告。未来可能会取消对静态地调用非静态方法的支持。
从PHP8开始,这个方法不再起作用。
在PHP 8中,调用非静态方法的能力被最终移除。
调用非静态方法的能力已被移除。因此,在检查具有类名的非静态方法时,
is_callable()
将失败(必须使用对象实例进行检查)。
它最初是在PHP 7上弃用的。
对未声明为静态的方法进行静态调用已弃用,可能会在未来被删除。
不确定为什么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上测试过)。
$instance->staticFunc();
调用静态函数。 - Benjamin Crouzier