PHP:使用父类作为接口中的类型声明

时间:2018-08-13 11:18:28

标签: php oop

比方说,我有一个特定的模型,它是从“模型”扩展而来的

Class MyModel extends Model { ... }

对于每个模型,我想创建一个实现TranslatorInterface的Translator类

Interface TranslatorInterface {
    public function translate(Model $model);
}

但是我不想传递父类“ Model”,而是将确切的模型子传递给translate方法

Class MyTranslator implements TranslatorInterface {
    public function translate(MyModel $model) { 
        ... 
    }
}

我无法正常工作。

我知道我可以通过以下方法解决此问题

Class MyTranslator implements TranslatorInterface {
    public function __construct(MyModel $model) {
        $this->model = $model;
    }

    public function translate() {
        $this->model->doSomething();
        ...
    }
}

接口__construct方法未定义,translate()方法也未接收任何参数。

但是我想知道是否有可能像我上面尝试过的那样完成它。(如果没有,这就是为什么这是一个坏主意;))

2 个答案:

答案 0 :(得分:1)

从OOP角度:您正在更改函数签名:

在实现中,您还应该使用:

public function translate(Model $model){}

您可以将MyModel类型的参数传递给此函数。

所有MyModel都是Model,但并非所有Model都是MyModel,您可以具有Model的其他实现,这些实现可以传递给函数,但不是MyModel。

EDIT1:根据您的评论如下:

您可以检查每个隐含形式是否是所需类的实例:

Class MyTranslator implements TranslatorInterface {
    public function translate(Model $model) { 
      if (is_a($model, 'MyModel')) {
      echo "yes, you use to translate MyModel \n";
      }
    }
}

根据上下文,您可以使用此解决方案,但是我认为使用_constructor的解决方案是通过较小的更改来实现此目的的更好方法:

Class MyTranslator implements TranslatorInterface {
    public function __construct(Model $model) {
        $this->model = $model;
    }

    public function translate() {
        $this->model->doSomething();
        ...
    }
}

您只需要一个构造函数,它将使用基于Polimorphism的正确实现。

答案 1 :(得分:1)

这是禁止的,因为它违反了Liskov Substitution Principle

  

子类型中方法自变量的一致性。

这意味着可以更改方法,但前提是您必须扩大类型限制。目前,PHP不支持真实的contravariance。目前,您只能使用简单的parameter type widening,这意味着在接口的实现中可以省略参数类型。