简体   繁体   English

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

[英]“Class X extends Y (abstract), Y implements Z (interface). ”Cannot call abstract method of interface Z"

Here are my PHP abstraction classes. 这是我的PHP抽象类。 The bottom most class is one of the classes that will extend the abstract class and leave some of the complex calculation logic to the parent implementation. 最底层的类是扩展抽象类并将一些复杂的计算逻辑留给父实现的类之一。

The point of the interface class (the top most abstraction) is to force those lower implementations have their own static public function id($params=false){ method. 接口类(最顶层的抽象)的要点是强制那些较低的实现具有自己的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';
     }
}

The end result is that if I call: 最终的结果是,如果我打电话:

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

I get a fatal error: Fatal error: Cannot call abstract method MyInterface::id(); 我得到致命错误: Fatal error: Cannot call abstract method MyInterface::id();

Why is MyAbstraction::run() calling the id() method of its parent (interface) instead of the method found in its child (descendant) class? 为什么MyAbstraction::run()调用其父(接口)的id()方法而不是在其子(后代)类中找到的方法?

  1. All methods declared in an interface must be public; 在接口中声明的所有方法都必须是公共的; this is the nature of an interface. 这是界面的本质。 Reference - PHP interface 参考 - PHP界面

  2. You are using self::id() in MyAbstraction class, self always refers same class. 你在MyAbstraction类中使用self::id()self总是指同一个类。 reference self vs static 引用自我与静态

you should use static instead of self. 你应该使用静态而不是自我。 Refer below code. 请参阅以下代码。

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();

In above code static::id() will call function of class which is in context ie MyImplementation class. 在上面的代码中, static::id()将调用上下文中的类函数,即MyImplementation类。

This phenomenon known as Late Static Binding 这种现象称为后期静态绑定

"self" is reference to "MyAbstraction" class (itself). “self”是指“MyAbstraction”类(本身)。 So it try to search MyAbstraction::id() , and got an error. 所以它试图搜索MyAbstraction::id() ,并得到一个错误。

  1. You shoud use "static" keyword static::id(); 你应该使用“static”关键字static::id();
  2. You cannot use $this in static method ($this->id) . 你不能在静态方法中使用$ this ($this->id)
  3. All of your methods are static, so You do not need instantiate an object. 您的所有方法都是静态的,因此您不需要实例化对象。 You can do the same with a static call: MyImplementation::run(); 您可以使用静态调用执行相同的操作: MyImplementation::run();

Try to replace your self::id() by static::id() . 尝试用static::id()替换你的self::id() static::id()

You use the Late Static Bindings of PHP here. 你在这里使用PHP的Late Static Bindings

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实现接口的抽象类的方法重写 - Method overriding of abstract class that implements an interface 扩展一个抽象类,该抽象类扩展了另一个抽象类,并且需要重写父抽象类实现的接口 - Extend an abstract class that extends another abstract class and need to override the interface the parent abstract class implements 何时在PHP中使用extends / abstract和implements / interface - When to use extends/abstract and implements/interface in PHP 使用具体类型的接口类型提示实现抽象方法 - Implements a abstract method with interface type hint with a concrete typing class 抽象类,接口或抽象方法的用途是什么 - What is the use of an abstract class, interface or an abstract method 将花式URL解析为PHP中的变量(/ class / method / x / 1 / y / 1 / z / 1 /) - Parsing a fancy URL to variables in PHP (/class/method/x/1/y/1/z/1/) 无法在 Service-Repository 模式中调用抽象方法接口 - Cannot call abstract method interface in Service-Repository pattern 抽象类和接口在一起? - Abstract class and interface together? 当我的抽象类实现一个接口时,我应该创建抽象方法吗? - Should I create abstract methods when my abstract class implements an interface? (x && y || z)和(x AND y OR z)之间的差异 - Difference Between (x && y || z) and (x AND y OR z)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM