我相信这类问题每天都会被问到,但我很难理解为什么这个哺乳动物对象被实例化为一只猫,并报告它的名字是Morris。然而,与大多数猫不同的是,它没有9条生命。如果对象不是猫,为什么它报告自己的名字是Morris?
class Mammal {
int temp;
String name = "George";
public Mammal() {
temp = 98;
}
public String getName() {
return name;
}
}
class Cat extends Mammal {
int lives;
String name = "Morris";
public Cat() {
lives = 9;
}
public String getName() {
return name;
}
}
public class Inheritance {
public static void main(String[] args) {
Mammal mm = new Cat();
System.out.println("Mam Temp:" + mm.temp);
//System.out.println("Cat Lives:" + mm.lives); <-- error
System.out.println("Mam Name:" + mm.getName());
}
}发布于 2011-10-29 00:54:17
这里有两个相关但具体分离的概念。
对象的运行时类型将决定它在运行时的行为方式。它由您在使用new关键字时调用的构造函数决定。
变量的静态类型指示代码如何与该变量(以及它引用的对象)交互或引用该变量。它由您在声明变量(或字段、参数等)时指定的类型决定。
在本例中,变量的静态类型是Mammal,而它所指向的对象的运行时类型是Cat。因此,虽然它在运行时的行为类似于Cat,并将其名称显示为“Morris”,但在编译时,编译器只知道它是一个Mammal,不能引用lives变量(该变量是在Cat中定义的,而不是在Mammal中定义的)。
发布于 2011-10-29 00:50:31
因为该变量是在Mammal mm = new Cat();行中设置的Mammal类型。Mammal类不包含变量lives,因此它抛出错误。但是,如果执行((Cat)mm).lives,应该会得到正确的结果,因为您将mm变量强制转换为Cat类型(它被初始化为该类型)。
编辑
此外,您还覆盖了Cat类中的getName()方法,该方法“隐藏”了Mammal类中的方法。您将mm创建为一个类型Mammal,但实际上它是一个Cat,因此对mm上的getName()方法的调用将调用子方法getName(),后者返回"Morris"而不是"George"。
发布于 2011-10-29 00:52:21
您创建了一个Cat实例,但您将其视为一个Mammal。Mammal.lives不存在,这就是当您尝试打印mm.lives时出现错误的原因。
顺便说一句,这是一个很好的例子,说明了为什么继承可能是危险的,应该谨慎使用。猫和哺乳动物是通过继承紧密耦合在一起的,所以你必须理解这两个类以及它们是如何交互的,以便理解处理Cat的代码。
https://stackoverflow.com/questions/7932262
复制相似问题