PHP接口实现拒绝参数的子类

时间:2011-01-24 13:59:45

标签: php interface subclass type-hinting interface-implementation

考虑一下:

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的子类,我看不出问题是什么。我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:5)

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

在您的情况下,CI更具限制性,因为它对doSomething参数有更精确的要求 - I.doSomething对任何A都可以。但C.doSomething需要A

的特定子类型

请注意,如果您将C.doSomething更改为接受任何A,则不会阻止您将B类型的对象传递给它。你不能只需要B,因为那样你就会破坏子类型合同。

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

答案 1 :(得分:2)

  

理论上,子类型对其函数参数可以更自由   并且更具体地说明他们的回归类型(但反之亦然)   这是你的情况)。实际上,编程语言可能需要   重写方法中的参数类型必须在任何地方都相同。

解决这个问题的工作很少 - 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") };
 }
}