为什么PHP traits不具有静态抽象方法?

前端之家收集整理的这篇文章主要介绍了为什么PHP traits不具有静态抽象方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
通过 PHP v5.3中的静态绑定,可以在接口中有效地声明静态方法;在PHP v5.4中具有特征,方法可以是静态还是抽象,但不能同时使用.这似乎是不合逻辑的和不一致的.

特别地,假设一个特征提供所有实现的接口,除了静态方法;除非该特性中声明了该方法,否则静态分析器将在特征内部引用任何引用.但是,在特征中提供具体的实现不再强制执行/使用类来提供自己的实现 – 这是危险的;抽象静态是理想的,但不允许.

这个矛盾的解释是什么?你会如何建议解决这个问题?

  1. interface MyInterface
  2. {
  3. public static function getSetting();
  4. public function doSomethingWithSetting();
  5. }
  6.  
  7. trait MyTrait
  8. {
  9. public abstract static function getSetting(); // I want this...
  10.  
  11. public function doSomethingWithSetting() {
  12. $setting = static::getSetting(); // ...so that I can do this
  13. /* ... */
  14. }
  15. }
  16.  
  17. class MyClass implements MyInterface
  18. {
  19. use MyTrait;
  20. public static function getSetting() { return /* ... */ }
  21. }
TL; DR:您可以在特征上定义抽象静态,但内部认为这是不好的做法,可能会在将来删除它.

没有多少咖啡因,但我会给它一个裂缝.

严格来说,抽象意味着子类必须实现,静态意味着这个特定类的代码.总而言之,抽象静态意味着“子类必须为此特定类实现代码”.完全正交的概念.

但是,PHP 5.3支持静态继承感谢LSB.所以我们实际上打开了这个定义:自己采用以前的静态定义,而static变为“这个特定类或其任何子类的代码”.抽象静态的新定义是“子类必须为此特定类或其任何子类实现代码”.这可能导致一些人在严格意义上认为静态混淆.参见例如bug #53081.

什么使特质如此特别的引出这个警告?那么看看实施通知engine code

  1. if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
  2. zend_error(error_type,"Static function %s%s%s() cannot be abstract",scope ? ZSTR_VAL(scope->name) : "",scope ? "::" : "",ptr->fname);
  3. }

代码表示​​允许抽象静态的唯一位置在接口内.特征不是唯一的,它是抽象静态的定义所独有的.为什么?那么我们的定义有一个小小的角落:

sub-class must implement code for this specific class or any of its sub-classes

使用此代码

  1. abstract class Foo {
  2. abstract public static function get();
  3. }

那个定义意味着我应该能够调用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.

  1. trait MyTrait
  2. {
  3. public function doSomethingWithSetting() {
  4. $service = new MyService($this);
  5. return $service->doSomethingWithSetting();
  6. }
  7. }
  8.  
  9. class MyService
  10. {
  11. public function __construct(MyInterface $object) {
  12. $this->object = $object;
  13. }
  14. public function doSomethingWithSetting() {
  15. $setting = $this->object->getSetting();
  16. return $setting;
  17. }
  18. }

感觉有点Rube Goldberg.可能会看静态的动机,并考虑重构它们.

猜你在找的PHP相关文章