2012-07-10 194 views
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类时出现错误。任何人都可以解释这个背后的原因吗? 更具体地说,问题是为什么一个方法不能接受期望基类型的子类型参数? 谢谢!传递需要基类对象的派生类对象

+1

请不要在提到Java时使用术语*基类*。这不是特定于Java,虽然有时候会用到。你应该使用术语*超类*。 – Lion 2012-07-10 06:10:51

+0

谢谢狮子!我将使用超级类从现在的 – Austin 2012-07-10 06:15:28

+0

顺便说一句,我使用术语“基类”,特别是当提到一个抽象类。 – Bohemian 2012-07-10 06:23:35

回答

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 { } 

两个AppleBananaFruitApple不是BananaBananaApple。所以,你不可能给Banana给予期望Apple的人,但是对于仅仅期望Fruit的人可以给BananaApple有效。

所以,

public void method(Fruit fruit) { 

没有相同的签名

public void method(Apple apple) { 

因为,如果是,那么这将意味着下具有相同的签名上面

public void method(Banana banana) { 

签名必须在重写(实现)方法时匹配。

+0

谢谢@Bhesh。但派生类拥有其超类的所有内容。那么,为什么不能通过而不是超级班呢?它是否需要类型铸造或任何这样的事情。我不清楚原因。 – Austin 2012-07-10 06:17:54

+0

@ user1513795:查看更新。 – 2012-07-10 06:19:01

+0

谢谢@BheshGurung。你的解释非常简单易懂。再次感谢! – Austin 2012-07-10 07:10:30

0

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

您可以选择使用bridge方法:

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

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

第二种方法是bridge方法,其职责是简单地发送您的请求到实际继承的方法。正如你所看到的桥梁方法是一个重载,而不是一个重载。

另一种选择是使用泛型。

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 

    } 
} 

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

相关问题