java可以在其他对象中调用父重写方法但不能调用子类型吗?

时间:2009-06-23 14:20:09

标签: java override

这是工作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设计像这样?

4 个答案:

答案 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进行比较,这样您就可以将结果与超类结合起来,运用您的创造力:)