继承和多态冲突

时间:2012-04-20 20:51:47

标签: java inheritance polymorphism

如果Fruit类是superClass而AppleOrange是Fruit的子类,  GoldenDeliciousMacintoshApple的子类。

假设给出以下声明:

Fruit fruit = new GoldenDelicious();
Orange orange = new Orange();

用解释

回答这个问题

假设方法makeAppleCiderApple类中定义。能够 fruit调用此方法?橙色可以调用这个方法???

我的回答是:可以 水果调用这个方法?没有因为没有明确的演员,必须做明确演员                           fruit实例,用于调用Apple类中定义的方法。剂量这个答案是真的????

3 个答案:

答案 0 :(得分:1)

这将深入研究变量的静态和动态类型。

Fruit fruit;

此行声明了一个变量fruit,其静态类型为Fruit。这种类型永远不会改变(毕竟它是静态的)并且是你通常会使用的类型。

fruit = new GoldenDelicious();

此行是为该变量指定值为GoldenDelicious的行。变量的动态类型确实会发生变化以反映此更改。毕竟,变量实际上现在包含GoldenDelicious。动态类型是你通常不会使用的东西,但它是你使用(邪恶)instanceof时使用的(它确保在正确的位置调用覆盖函数)。

现在,您要这样做:

fruit.makeAppleCider();

这不起作用。结果,我们基本上只知道静态类型,而静态类型Fruit对该方法一无所知。 (但是,在幕后,如果GoldenDeliciousMacintosh以不同方式实现该功能,动态类型将确保调用正确的版本。)

正如您在回答中提到的,显式强制转换可用于更改您正在使用的静态类型,因此您可以使其以这种方式工作。不过,最好不要这样做,因为应该避免演员阵容而不是“适当的OOP”。

总之,是的,你的回答是正确的。

(是的,我的描述有点技术性。我希望你能原谅我......)

答案 1 :(得分:0)

Fruit没有makeAppleCider方法的“知识”。 makeAppleCider在子类中定义,不是Fruit的成员。类只能访问它或其父项之一定义的方法。给定某个类的类,您必须跟踪类层次结构以查看可以访问的方法。您可以将变量的类型视为步骤备份类层次结构的起始位置。

如果您希望所有类都有访问权限的方法,请将其放在层次结构的根目录中。显然,使用该方法的逻辑应该是有意义的,否则使用您的代码的人会感到困惑。

答案 2 :(得分:0)

另一个选择当然是使用“接口” - 一种穷人的多重继承(但比完全多重继承更容易理解和实现)。

你可以,例如,有一个类似的界面(没有语法检查):

public interface CiderFruit {
    public void makeCider();
}

然后Apple可以实现界面:

public class Apple extends Fruit implements CiderFruit {
    ....
    public void makeCider() {
        doStuff();
    }
    ....
}

如果您有一个Quince类,它可以实现相同的界面,可以使用Apple或Quince,将其转换为CiderFruit(如果不确定它是Apple还是Quince),并调用makeCider()。 (也可以直接使用输入为Apple或Quince的引用来调用。)