特别地,假设一个特征提供所有实现的接口,除了静态方法;除非该特性中声明了该方法,否则静态分析器将在特征内部引用任何引用.但是,在特征中提供具体的实现不再强制执行/使用类来提供自己的实现 – 这是危险的;抽象静态是理想的,但不允许.
这个矛盾的解释是什么?你会如何建议解决这个问题?
interface MyInterface { public static function getSetting(); public function doSomethingWithSetting(); } trait MyTrait { public abstract static function getSetting(); // I want this... public function doSomethingWithSetting() { $setting = static::getSetting(); // ...so that I can do this /* ... */ } } class MyClass implements MyInterface { use MyTrait; public static function getSetting() { return /* ... */ } }
没有多少咖啡因,但我会给它一个裂缝.
严格来说,抽象意味着子类必须实现,静态意味着这个特定类的代码.总而言之,抽象静态意味着“子类必须为此特定类实现代码”.完全正交的概念.
但是,PHP 5.3支持静态继承感谢LSB.所以我们实际上打开了这个定义:自己采用以前的静态定义,而static变为“这个特定类或其任何子类的代码”.抽象静态的新定义是“子类必须为此特定类或其任何子类实现代码”.这可能导致一些人在严格意义上认为静态混淆.参见例如bug #53081.
什么使特质如此特别的引出这个警告?那么看看实施通知的engine code:
if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) { zend_error(error_type,"Static function %s%s%s() cannot be abstract",scope ? ZSTR_VAL(scope->name) : "",scope ? "::" : "",ptr->fname); }
该代码表示允许抽象静态的唯一位置在接口内.特征不是唯一的,它是抽象静态的定义所独有的.为什么?那么我们的定义有一个小小的角落:
sub-class must implement code for this specific class or any of its sub-classes
使用此代码:
abstract class Foo { abstract public static function get(); }
那个定义意味着我应该能够调用Foo :: get.毕竟Foo是一个类(看到那个关键字“class”),而在严格的定义中,get就是要在这个类Foo中实现的.但是很明显,没有任何意义,因为我们回到了严格静态的正交性.
如果您尝试使用PHP,您可以获得唯一的理由响应:
Cannot call abstract method Foo::get()
所以因为PHP添加静态继承,它必须处理这些角落的情况.这是特征的本质.一些其他语言(C#,Java等)没有这个问题,因为它们采用严格的定义,根本不允许抽象静态.为了摆脱这种情况,简化引擎,我们可能会在将来强制执行这个“仅在接口中的抽象静态”规则.因此,E_STRICT.
我会使用服务代理来解决问题:
I have common method I want to use in several classes. This common method relies on a static method that must be defined externally to the common code.
trait MyTrait { public function doSomethingWithSetting() { $service = new MyService($this); return $service->doSomethingWithSetting(); } } class MyService { public function __construct(MyInterface $object) { $this->object = $object; } public function doSomethingWithSetting() { $setting = $this->object->getSetting(); return $setting; } }
感觉有点Rube Goldberg.可能会看静态的动机,并考虑重构它们.