-1

如果一个Fruit类是超类,Apple并且Orange是 Fruit 的子类,GoldenDelicious并且Macintosh是 的子类Apple

假设给出以下声明:

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

用解释回答这个问题

假设方法makeAppleCider是在类中定义的Apple。可以 fruit调用这个方法吗?橙子可以调用这个方法???

我的回答是:水果可以调用这个方法吗?没有因为没有显式转换,必须对水果实例进行显式转换才能调用 Apple 类中定义的方法。这个答案是真的吗???

4

3 回答 3

1

这深入到变量的静态和动态类型。

Fruit fruit;

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

fruit = new GoldenDelicious();

这一行是GoldenDelicious为该变量分配一个值的行。变量的动态类型确实会发生变化以反映这种变化。毕竟,变量实际上包含一个GoldenDeliciousnow。动态类型是您通常不会使用的东西,但是当您使用 (evil) 时会使用它instanceof(它确保在正确的位置调用被覆盖的函数)。

现在,你想这样做:

fruit.makeAppleCider();

这行不通。果不其然,我们基本上只知道静态类型,而静态类型Fruit对那个方法一无所知。(然而,在幕后,如果以不同GoldenDeliciousMacintosh方式实现函数,动态类型将确保调用正确的版本。)

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

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

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

于 2012-04-20T21:22:17.737 回答
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 的引用直接调用。)

于 2012-04-20T21:15:21.510 回答
0

AFruit没有该makeAppleCider方法的“知识”。makeAppleCider在子类中定义并且不是 的成员Fruit。一个类只能访问它或它的一个父类定义的方法。给定一个特定类型的类,您必须追溯类层次结构以查看您可以访问哪些方法。您可以将变量的类型视为返回类层次结构的起点。

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

于 2012-04-20T21:03:40.427 回答