比方说,我有一个特定的模型,它是从“模型”扩展而来的
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()方法也未接收任何参数。
但是我想知道是否有可能像我上面尝试过的那样完成它。(如果没有,这就是为什么这是一个坏主意;))
答案 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,这意味着在接口的实现中可以省略参数类型。