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よりも制限が厳しくなります-どの場合でも問題ありませんが、次の特定のサブタイプが必要ですIdoSomethingI.doSomethingAC.doSomethingA

C.doSomethingいずれかを受け入れるように変更しAた場合、タイプのオブジェクトを渡すことを妨げるものは何もないことに注意してくださいBBサブタイピング契約を破ることになるので、だけを要求することはできません。

理論的には、サブタイプは関数の引数についてより寛大であり、戻り型についてより具体的である可能性があります(ただし、あなたの場合のように、その逆はありません)。実際には、プログラミング言語では、オーバーライドされたメソッドの引数タイプがどこでも同じである必要がある場合があります。

于 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 に答える