考虑一下:
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 拒绝要求第一个参数与接口(interface) (I) 中定义的类型 (A) 完全相同的实现。由于 B 是 A 的子类,所以我看不出有什么问题。我在这里遗漏了什么吗?
最佳答案
class C implements I
意味着C
和I
之间一定存在子类型关系。这意味着 C
类型的对象应该可以在任何需要 I
类型的对象的地方使用。
在您的情况下,C
比 I
更具限制性,因为它对其 doSomething
参数有更精确的要求 -- I。 doSomething
适用于任何 A
但 C.doSomething
需要 A
请注意,如果您将 C.doSomething
更改为接受任何 A
,那么没有什么可以阻止您将类型为 B
的对象传递给它。你不能只需要 B
,因为那样你会破坏子类型契约(Contract)。
从理论上讲,子类型可以更自由地处理它们的函数参数,更具体地处理它们的返回类型(但反之亦然,就像你的情况一样)。在实践中,编程语言可能要求重写方法中的参数类型在所有地方都必须相同。
关于PHP 接口(interface)实现拒绝参数的子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4782824/