传递期望基类对象的派生类对象

时间:2012-07-10 06:03:48

标签: java

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类时出错。任何人都可以解释一下这背后的原因吗? 更具体地说,问题是为什么方法不能接受期望基类型的子类型参数? 谢谢!

2 个答案:

答案 0 :(得分: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不是BananaBanana不是Apple。因此,您无法真正将Banana提供给期望Apple的人,但是对于只有BananaApple的人来说是有效的期待Fruit

所以,

public void method(Fruit fruit) {

没有相同的签名
public void method(Apple apple) {

因为,如果是,则表示以下内容具有与上述相同的签名

public void method(Banana banana) {

签名必须匹配,同时覆盖(实现)方法。

答案 1 :(得分:0)

您正在更改方法的签名,因此,Java只能假设您的意图是“重载”具有相同名称和不同参数的现有方法。

您也可以使用桥接方法:

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

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

第二种方法是桥接方法,它的职责是将请求转发给实际的继承方法。正如您所看到的,桥接方法是重载,而不是覆盖。

另一种选择是使用泛型。

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

    }
}

最终,泛型版本与第一个选项完全相同,也就是说,编译器会综合生成桥接方法。如果您对类进​​行反编译,您会发现它确实如此。