2011-05-07 82 views
0

类C具有void方法m,但不带参数。另一个D类扩展C并覆盖m。每个类都有一个没有参数的构造函数。在下面的每一个中,说出它是否合法,如果是,那么将使用m的哪个定义。Java继承

我)C x = new D(); x.m();

II)D x = new C(); x.m();

我想我是合法的,并且ii并不违法。不知道我怎样才能解决这个问题,欢迎提供任何提示。

回答

2

回答这个问题的最好方法是写一些代码,看看会发生什么。在您的m的实现中使用System.out.println("method called from C");来确定调用哪个实现。话虽如此,重写一个方法的重点就是使新的实现能够被使用。如果你的对象是C,那么将调用C的方法。如果您的对象是D类型,那么D的方法将被调用,而不管参考是什么类型。

第一个答案:

C x = new D(); 

是合法的,因为和类型D的对象是C,以及(因为D延伸C)。

第二个答案:

D x = new C(); 

合法的,因为到D参考无法保持其超C的对象。

1

是的,你是对的。

(i)是合法的,这将是D的是获取运行m方法(这被称为多态性)。 (ii)是非法的,甚至不会编译,因为D不是超类型的C(实际上,它是一个子类型)。我们可以把它写它作为编译:

D x = (D) new C(); x.m(); 

,但随后会在运行时失败了ClassCastException

1

尝试从“是”的关系来考虑继承。

如果D extends C那么这意味着每个d是C,但并不意味着每一个C是D.

要应用的思维,问题转化为一个“是”的问题。

C x = new D()

是需要一个new D()C的声明。

String s = new Object(),问问自己“是new Object() a String?”反之亦然呢?

祝你好运学习OOP。

+0

非常感谢您的快速回复。你已经帮我:-) – Paradox 2011-05-07 13:06:28

0

i)是合法的,ii)不是。很容易看出你是否使用了一个隐喻,比如C类是Animal,D类是Dog,m()是makeNoise。 现在有一个动物类变量并为其指定一个狗是合法的(因为狗是“动物”),但是将动物实例化并将它分配给狗是不合法的,因为狗比动物更具体(我们不能说动物是“狗”)。

现在对于方法:该方法总是在运行时类型上调用,而不是在变量类型上调用(所有方法调用在Java中都是所谓的虚拟),所以在i)它调用m()方法D级,而不是C级。