这是一个漫长而悲伤的故事。
当PHP 5.2首次引入此警告时,该语言还没有后期的静态绑定。如果您不熟悉后期的静态绑定,请注意,这样的代码将无法正常工作:
<?php
abstract class ParentClass {
static function foo() {
echo "I'm gonna do bar()";
self::bar();
}
abstract static function bar();
}
class ChildClass extends ParentClass {
static function bar() {
echo "Hello, World!";
}
}
ChildClass::foo();
撇开严格模式警告,上面的代码不起作用。中的self::bar()
调用foo()
显式引用的bar()
方法ParentClass
,即使foo()
被称为的方法ChildClass
。如果您尝试在严格模式关闭的情况下运行此代码,则会看到“ PHP致命错误:无法调用抽象方法ParentClass :: bar() ”。
鉴于此,PHP 5.2中的抽象静态方法毫无用处。在整个点使用抽象的方法是,你可以写调用该方法不知道什么实现它的将是调用代码-然后提供不同的子类不同的实现。但是,由于PHP 5.2没有提供一种干净的方法来编写父类的方法,而该方法会调用子类的静态方法(在该子类上调用该方法),因此无法使用抽象静态方法。因此abstract static
,PHP 5.2中的任何用法都是不好的代码,可能是由于对该self
关键字的工作方式的误解而引起的。对此发出警告是完全合理的。
但是随后PHP 5.3引入了通过static
关键字引用在其上调用方法的类的功能(与self
关键字不同,该关键字始终引用定义该方法的类)。如果在上面的示例中更改self::bar()
为static::bar()
,则在PHP 5.3及更高版本中可以正常工作。您可以在New self vs. new static上了解有关self
vs的更多信息。static
添加了static关键字后,用于abstract static
发出警告的clear参数就消失了。后期静态绑定的主要目的是允许在父类中定义的方法调用将在子类中定义的静态方法。考虑到后期静态绑定的存在,允许抽象静态方法似乎是合理且一致的。
我想,您仍然可以为保持警告辩护。例如,您可能会争辩说,由于PHP允许您调用抽象类的静态方法,因此在上面的示例中(即使通过用替换self
了它,也可以修复static
),您正在公开一个损坏的公共方法ParentClass::foo()
,并且您真的不想暴露。使用非静态类(即使所有方法的实例方法并使所有子方法成为单例或诸如此类)将解决此问题,因为不能被抽象化,因此其实例方法不能被实例化。叫做。我认为这个论点很弱(因为我认为公开ParentClass
ParentClass
ParentClass::foo()
没什么大不了的,使用单例而不是静态类通常是不必要的冗长和丑陋),但是您可能会不同意-这有点主观。
因此,基于此论点,PHP开发人员使用该语言保留了警告,对吗?
呃,不完全是。
上面链接的PHP错误报告53081呼吁删除警告,因为添加该static::foo()
构造已使抽象静态方法合理且有用。Rasmus Lerdorf(PHP的创建者)首先将请求标记为伪造,然后经过一连串的错误推理来试图证明警告的合理性。然后,最后进行这种交换:
乔治
我知道但是:
abstract class cA
{
//static function A(){self::B();} error, undefined method
static function A(){static::B();} // good
abstract static function B();
}
class cB extends cA
{
static function B(){echo "ok";}
}
cB::A();
拉斯穆斯
是的,这就是它应该如何工作的。
乔治
但这是不允许的:(
拉斯穆斯
不允许什么?
abstract class cA {
static function A(){static::B();}
abstract static function B();
}
class cB extends cA {
static function B(){echo "ok";}
}
cB::A();
这很好。您显然不能调用self :: B(),但是static :: B()可以。
Rasmus声称他的示例中的代码“可以正常工作”是错误的;如您所知,它会发出严格的模式警告。我猜他在没有打开严格模式的情况下进行测试。无论如何,一个困惑的拉斯穆斯将请求错误地关闭为“伪造”。
这就是为什么警告仍然使用该语言。这可能不是一个完全令人满意的解释-您可能来到这里是希望警告的合理理由。不幸的是,在现实世界中,有时候选择是来自平凡的错误和错误的推理,而不是理性的决策。这只是其中一次。
幸运的是,作为PHP RFC的一部分,可估算的Nikita Popov已从PHP 7语言中删除了该警告:重新分类E_STRICT声明。最终,理智性盛行,一旦PHP 7发布,我们所有人都可以愉快地使用abstract static
而不会收到这个愚蠢的警告。