这是工作java代码
class Cup {
public String sayColor() {
return "i have a color .";
}
}
class TCup extends Cup{
public String sayColor(){
System.out.println(super.getClass().getName());
return super.sayColor()+"color is tee green.";
}
}
class MyTCup extends TCup {
public String sayColor(){
System.out.println(super.getClass().getName());
return super.sayColor()+"but brushed to red now!";
}
}
class Test {
public static void main(String[] args) {
Cup c = new MyTCup();
System.out.print(c.sayColor());
}
}
并运行Test类打印
MyTCup
MyTCup
i have a color .color is tee green.but brushed to red now!
问题1:
在运行时,对象C的类型是MyTCup,但它总是可以调用super方法。在初始化对象后,MyTCup中的内存中有一个方法堆栈,然后可以像运行代码一样在运行时调用吗?
问题2:
没有办法在其他对象中调用super方法。我知道,c ++可以随时转换为调用parent方法。为什么java设计像这样?
答案 0 :(得分:68)
你不能在其他对象中调用super方法 - 这会违反封装。重点是对象控制其重写方法的作用。例如,您可以覆盖集合的add
方法以在某些情况下抛出异常,因此可以确保仅将“有效”项添加到集合中。如果打电话者可以用演员来绕过它,那将毫无意义!
对象为自己调用super.foo()
的唯一原因是通过使用父实现来启用一个调用。这取决于班级中的代码,以确保它只能做到明智。再次,要采用加载项集合示例,如果集合覆盖add
,则必须使用某种方式将已验证的项目添加到集合中,它将执行此操作与super.add()
。
请注意,出于与encapuslation相同的原因,您只能 调用您的父实现,而不是祖父项实现 - 因此super.foo()
有效,但super.super.foo()
不是
答案 1 :(得分:1)
1:
你的问题不太清楚。 “在运行时调用代码”是什么意思?如果你问实例c如何知道它的超类是什么,那么是的,类层次结构存储在内存中,并且可以被VM访问。
2:
Java实际上允许您将实例转换为其父实例。只是在实例上调用方法总是使用实例的实际类,而不是它的编译时类。即在Java中,所有方法都是C ++中称为“虚拟”的方法。为什么这个决定我不知道。
编辑:实际上,Jon Skeet非常清楚地解释了为什么你不能在子类的实例上调用超类的方法,所以现在我知道了: - )。
答案 2 :(得分:0)
你可以在子类中定义一个新的辅助方法,这样你就不会覆盖原来的 - 调用它 - 它可以调用super方法,具体取决于你想要的。
答案 3 :(得分:0)
实际上你可以,但你必须使用一种方法,所以它只适用于你的代码 在超类中,将参数“Class”添加到方法中,如:
public String sayColor(Class classFilter){...
现在,在每次覆盖时,检查当前子类是否是指定的过滤器之一,如:
if(TCup.class!=classFilter)return super.sayColor(classFilter);
return "some text for TCup only";
我以独家方式编码。您可以添加更多参数,或者与null进行比较,这样您就可以将结果与超类结合起来,运用您的创造力:)