“X类扩展Y(抽象),Y实现Z(接口)。”不能调用接口Z的抽象方法“

时间:2016-01-05 09:00:40

标签: php

这是我的PHP抽象类。最底层的类是扩展抽象类并将一些复杂的计算逻辑留给父实现的类之一。

接口类(最顶层的抽象)的要点是强制那些较低的实现具有自己的static public function id($params=false){方法。

// My top level abstraction, to be implemented only by "MyAbstraction"
interface MyInterface{
      static public function id();
}
// My second (lower) level of abstraction, to be extended
// by all child classes. This is an abstraction of just the
// common heavy lifting logic, common methods and properties.
// This class is never instantiated, hence the "abstract" modifier.
// Also, this class doesn't override the id() method. It is left
// for the descendant classes to do.

abstract class MyAbstraction implements MyInterface{

    // Some heavy lifting here, including common methods, properties, etc
    // ....
    // ....

     static public function run(){
          $this->id = self::id(); // This is failing with fatal error
     }
}
// This is one of many "children" that only extend the needed methods/properties
class MyImplementation extends MyAbstraction{

     // As you can see, I have implemented the "forced"
     // method, coming from the top most interface abstraction
     static public function id(){
         return 'XXX';
     }
}

最终结果是,如果我打电话:

$o = new MyImplementation();
$o->run();

我收到致命错误: Fatal error: Cannot call abstract method MyInterface::id();

为什么MyAbstraction::run()调用其父(接口)的id()方法而不是在其子(后代)类中找到的方法?

3 个答案:

答案 0 :(得分:4)

  1. 接口中声明的所有方法都必须是公共的;这是界面的本质。 Reference - PHP interface

  2. 您在self::id()班级中使用MyAbstractionself始终引用相同的班级。 reference self vs static

  3. 你应该使用静态而不是自我。请参阅下面的代码。

    interface MyInterface{
        public function id();
    }
    
    abstract class MyAbstraction implements MyInterface{
    
        public $id;
        // Some heavy lifting here, including common methods, properties, etc
        // ....
        // ....
    
        public function run(){
            $this->id = static::id(); // This is failing with fatal error
        }
    }
    
    class MyImplementation extends MyAbstraction{
    
        // As you can see, I have implemented the "forced"
        // method, coming from the top most interface abstraction
        public function id(){
            return 'XXX';
        }
    }
    
    $o = new MyImplementation();
    $o->run();
    

    在上面的代码中,static::id()将调用类的函数,该函数位于上下文中,即MyImplementation类。

    这种现象称为Late Static Binding

答案 1 :(得分:2)

“self”是对“MyAbstraction”类(本身)的引用。因此,它尝试搜索MyAbstraction::id(),并收到错误。

  1. 您应该使用“静态”关键字static::id();
  2. 您不能在静态方法($this->id)中使用$ this。
  3. 您的所有方法都是静态的,因此您不需要实例化对象。 您可以使用静态调用执行相同的操作:MyImplementation::run();

答案 2 :(得分:1)

尝试将self::id()替换为static::id()

您可以在此处使用PHP的Updated JSFiddle