【发布时间】:2013-11-20 00:12:42
【问题描述】:
我在 Java 考试中遇到了一个关于继承的问题。事情是这样的:
class A{
public int getInt(){
return 0;
}
}
class B extends A{
public int getInt(){
return 60;
}
}
class C extends B{
public int getInt(){
return 150;
}
}
class Z4{
public static void main(String[] args){
A c1 = new C();
B c2 = new C();
C c3 = new C();
System.out.println(c1.getInt() + " " + c2.getInt() + " " + c3.getInt());
}
}
代码打印出“150 150 150”
我明白为什么会这样:变量是运算符左侧表示的类型,而对象是运算符右侧表示的类型。由于所有对象都是 C 类型,因此它们都使用 C 的重写方法。
此外,如果 C 类有一个重载(而不是重载)方法,前两个变量将无法使用它,因为它们的变量类型没有该方法签名。
附带说明,超类类型的变量可以引用子类类型的对象。但是子类类型的变量不能引用超类类型的对象。 “超级 myObject = new Sub();”作品。 “Sub myObject = new Super();”没有。
我的第一个问题是:上述陈述是否正确?我的第二个问题是:你什么时候会这样做?
根据我非常有限的经验,我制作了超类类型的 ArrayList,并用各种子类的对象填充它。我看到它派上用场了。但是是否存在您专门创建与其对象不同类型的变量的情况?你输入过“SuperClass myObject = new SubClass();”吗?我看不出有实际用途。
【问题讨论】:
-
我的猜测是你过于关注它是一个局部变量的事实。为了保持测试的可读性,这可能是一种简化,仅此而已。看到 C# 的
var关键字(隐式将变量类型作为其初始化表达式的类型)可能是常用的,我猜下面答案中给出的原因比其他任何东西都更具追溯性。至于我自己,我会使用List foo = new ArrayList(),因为List打字更短。 -
@millimoose 我认为 C#
var或 C++auto与此处无关。首先,在具有该特性的语言中,将实现从例如 HashSet 更改为 Tree 或反之亦然,甚至更容易。您可以在任何合理的 Java 指南或更早的 S.O. 中找到将变量声明为接口的建议。 stackoverflow.com/questions/1484445/… -
@AndrewLazarus 我主要是在解决这个答案,说它比通过比较返回时隐含的向上转换要好。另外,我想说的是,当您不依赖于该实现的具体细节时,换出实现(我认为这对于局部变量及其非常有限的范围是一个绝对可笑的问题)更容易,实际上是在输入因为界面将帮助您完成。在搜索和替换框中保存一次单击似乎并不是一个很大的实际优势,尤其是在静态类型语言中。
标签: java inheritance