8

考虑一下:

class A{}

class B extends A{}

interface I{
 // expects object instanceof A
 function doSomething(A $a);
}

class C implements I
{
 // fails ????
 function doSomething(B $b){}
}

在我的概念中,上面应该可以工作,但它不会因为 php 拒绝要求第一个参数与接口 (I) 中定义的类型 (A) 完全相同的实现。由于 B 是 A 的子类,我看不出有什么问题。我在这里错过了什么吗?

4

2 回答 2

8

class C implements IC意味着和之间必须存在子类型关系I。这意味着类型对象C应该可以在I需要类型对象的任何地方使用。

在您的情况下C,比I因为它对其doSomething论点有更精确的要求而更具限制性 -I.doSomething任何都可以,AC.doSomething需要特定的子类型A

请注意,如果您更改C.doSomething为接受任何A,那么没有什么可以阻止您将类型的对象传递给它B。你不能要求 only B,因为那样你会破坏子类型合同。

从理论上讲,子类型可以对它们的函数参数更自由,对它们的返回类型更具体(但反之亦然,就像你的情况一样)。在实践中,编程语言可能要求重写方法中的参数类型必须在任何地方都相同。

于 2011-01-24T14:11:53.173 回答
3

从理论上讲,子类型可以对它们的函数参数更自由,对它们的返回类型更具体(但反之亦然,就像你的情况一样)。在实践中,编程语言可能要求重写方法中的参数类型必须在任何地方都相同。

instanceof解决这个问题的方法很少:

class A{}

class B extends A{}

interface I{
 // expects object instanceof A
 function doSomething(A $a);
}

class C implements I
{

 function doSomething(A $b){
   if($b is instance of B){
   //do something
   }else{throw new InvalidArgumentException("arg must be instance of B") };
 }
}
于 2013-11-02T12:20:55.490 回答