了解PHP静态方法的处理(不能静态调用非静态方法)

3
<?php

class T {
        public function x(){
                return true;
        }    
}
var_dump(T::x());

class X {
        public function x(){
                return true;
        }

}    
var_dump(X::x());

这段代码的结果是:
bool(true)
PHP Fatal error:  Non-static method X::x() cannot be called statically in test.php on line 16

为什么T::x()能正常工作(实际上应该失败),而X::x()失败了(按照预期)?

1
well, self, parentstatic 也在进行非静态调用。你确定 $x = T::x(); 是成功的吗?! - bwoebi
请注意,在testY()中,您正在创建一个T对象,但没有创建X对象。这似乎会产生差异。 - Dillon Welch
@bwoebi 这正是我在这一切中发现奇怪的地方。我复制粘贴了我正在运行的核心。随意复制并查看是否有任何不同。另外,我将更新我的php / phpunit版本,这可能很有用。 - gcb
1
@gcb 请稍微修改一下你的问题,因为它实际上与phpunit完全无关...(而且应该通过更明显的搜索查询被谷歌搜索到...) http://3v4l.org/l5v8p 更全面地回答了这个问题... - bwoebi
@gcb 是因为你的 error_reporting 设置。设置 error_reporting(-1); 然后你就能看到它了(但也取决于你所使用的 PHP 版本)。 - bwoebi
显示剩余3条评论
1个回答

3

X::x() 是一个 PHP4 风格的构造函数,因为它与该类名称相同。以静态方式调用类的构造函数会引发致命错误:

无法以静态方式调用非静态方法 X::x(),假定 $this 从不兼容的上下文调用

实际上,对于所有非静态魔术方法都是如此,正如您在实现中所看到的:http://lxr.php.net/xref/PHP_5_5/Zend/zend_compile.c#1636

唯一可能隐式以静态方式调用(并引发 E_STRICT)的情况是当函数没有特殊处理时:

if (some large if/else's for the magic methods) {
    // flag isn't set…
} else {
    CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
}

@gcb 因为 T::x() 不是 PHP4 风格的构造函数(也不是一种魔术方法,允许从不兼容的上下文进行静态调用)?为了向后兼容,如果 PHP 5 找不到给定类的 _construct() 函数,并且该类没有从父类继承一个构造函数,则它将搜索旧式构造函数函数,名称为类名。 来自 http://php.net/manual/en/language.oop5.decon.php - bwoebi
我仍然看不出T::x()和X::x()有什么不同。如果我从代码中删除创建new T()的第一个测试,同样的事情会发生。T::x()不会抛出错误,但X::()会。 - gcb
2
@gcb X::x() 是构造函数,因为方法名(x)等于类名(X)(忽略大小写)。T::x() 不是构造函数,因为方法名(x)不等于类名(T)。正如我在我的答案中所说:对构造函数的静态调用是致命的。 - bwoebi
啊!当然了!抱歉,不知道为什么之前即使有解释也没看到! - gcb
1
请注意,调用类时大小写似乎不敏感,因此x和X是相同的。 - Dvid Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接