0
public abstract class AbstractClass 
{
    public abstract void AbstractClassMethod();
}


public class DerivedClass extends AbstractClass {

    @Override
    public void AbstractClassMethod() {
        // TODO Auto-generated method stub

    }

}



public interface InterfaceObject 
{
    public void InterfaceObjectMethod(AbstractClass oAbstractClass);
}



public class TestAbstractParam implements InterfaceObject {

    @Override
    public void InterfaceObjectMethod(AbstractClass oAbstractClass) {
        // TODO Auto-generated method stub

    }

}



public class TestDerivedParam implements InterfaceObject {

    @Override
    public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
        // TODO Auto-generated method stub

    }

}

TestDerivedParam クラスのコンパイル中にエラーが発生しました。誰かがこの背後にある理由を説明できますか? より具体的には、メソッドが基本型を期待している子型パラメーターを受け入れることができないのはなぜですか? ありがとうございました!

4

2 に答える 2

1

TestDerivedParamメソッドで

public void InterfaceObjectMethod(DerivedClass oDerivedClass) {

と同じではありません

public void InterfaceObjectMethod(AbstractClass oAbstractClass);

InterfaceObject

@Overrideアノテーションを使用していますが、同じメソッドシグネチャを使用していません。


より具体的には、問題は、メソッドが基本型を期待している子型パラメーターを受け入れることができない理由です。

以下の例を参照してください。

public class Fruit { }

public class Apple extends Fruit { }

public class Banana extends Fruit { }

AppleBananaは両方ですFruitが、そうでAppleはなくBanana、でBananaはありませんAppleBananaしたがって、期待している人に実際に与えることはできませんが、を期待している人にまたはAppleを与えることは有効です。BananaAppleFruit

それで、

public void method(Fruit fruit) {

と同じ署名がありません

public void method(Apple apple) {

なぜなら、もしそうなら、それは以下が上記と同じ署名を持っていることを意味するでしょう

public void method(Banana banana) {

また、メソッドをオーバーライド(実装)する際に署名が一致する必要があります。

于 2012-07-10T06:10:22.447 に答える
0

メソッドのシグニチャーを変更しているため、Javaは、同じ名前と異なるパラメーターを持つ既存のメソッドを「オーバーロード」することのみを想定できます。

または、ブリッジ方式を使用することもできます。

@Override
public void InterfaceObjectMethod(AbstractClass oDerivedClass) {
   // TODO Auto-generated method stub
}

public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
   InterfaceObjectMethod((AbstractClass)oDerivedClass);
}

この2番目のメソッドはブリッジメソッドであり、その責任は単にリクエストを実際の継承されたメソッドに転送することです。ご覧のとおり、ブリッジメソッドはオーバーロードであり、オーバーライドではありません。

別のオプションは、ジェネリックを使用することです。

interface InterfaceObject<T extends AbstractClass> 
{
    public void InterfaceObjectMethod(T oAbstractClass);
}


class TestAbstractParam implements InterfaceObject<AbstractClass> {

    @Override
    public void InterfaceObjectMethod(AbstractClass oAbstractClass) {
        // TODO Auto-generated method stub

    }
}

class TestDerivedParam implements InterfaceObject<DerivedClass> {

    @Override
    public void InterfaceObjectMethod(DerivedClass oDerivedClass) {
        // TODO Auto-generated method stub

    }
}

最終的に、ジェネリックバージョンは最初のオプションとまったく同じように動作します。つまり、ブリッジメソッドはコンパイラによって合成的に生成されます。クラスを逆コンパイルすると、まさにそれが実行されることに気付くでしょう。

于 2012-07-10T06:10:52.350 に答える