方法调用另一个被覆盖的方法,该方法在子类中调用?

时间:2011-11-07 13:55:16

标签: java inheritance override

如果我有2个类,其中一个是具有以下内容的父类:

public class Parent {
    ...
    public void method1() {
        method2();
    }

    public void method2() {
    }
}

然后在子类中

public class Child extends Parent {
    ...
    public void method2() {
        ...
    }
}

如果我运行以下代码:

Child c = new Child();
c.method1();

调用哪个版本的method2?

5 个答案:

答案 0 :(得分:5)

Java中的所有方法都是virtual,这意味着它将被调用Child.method2(即使调用是从Parent的上下文完成的)。

如果Parent.method1的正确性依赖于method2的实施,则应该采用不同的方式进行设计:

public class Parent {
    ...
    public void method1() {
        method2impl();
    }

    public void method2() {
        method2impl();
    }

    // make it private or final.
    public final method2impl() {
        ...
    }
}

答案 1 :(得分:3)

将调用

Child#method2,因为它会覆盖父级的。{/ p>

答案 2 :(得分:3)

一旦创建了Child类型的对象,那就是它的运行时类型。这不会改变,无论演员阵容或你做什么。调用方法时,将执行该运行时类型的实现。如果该类型没有自己的实现,它将委托给父类。

即使你调用method1中定义的Parent,一旦该方法调用method2,它将解析为对象的运行时类型的实现。如果那是Child,那就是将要调用的类'方法。

请注意,此动态行为与选择基于参数类型的方法不同,这是静态完成的。请按照以下类别定义......

public void methodTest(Parent p) {} //Let's call this "first method"
public void methodTest(Child c) {} //Let's call this "second method"

Parent p = new Parent();
Child c = new Child();

//Assume a is a variable of some type that implements the above methods
a.methodTest(p); //Will call first method
a.methodTest(c); //Will call second method
a.methodTest((Parent)c); //WILL CALL FIRST METHOD!

因此,静态地选择基于参数类型的方法。它不会根据运行时类型选择不同的方法。

但是根据调用它的对象选择一个方法取决于该对象的运行时类型。这就是允许我们覆盖子类中方法行为的原因。

答案 3 :(得分:0)

public class Parent {
    public void method1() {
        method2();
    }
    public void method2() {
        System.out.println("parent m 2");
    }
}
public class Child extends Parent {
    public void method2(){
        System.out.println("child m 2");
    }
}
public class Main {
    public static void main(String[] args) {
        Child c = new Child();
        c.method1();
        System.out.println("________________");
        c.method2();
    }
}

输出将是:

child m 2
________________
child m 2

答案 4 :(得分:0)

我还有一些问题要问你:

public interface CanDoMethod1 {
    public void method1();
}

public class Parent implements CanDoMethod1 {
    public void method1() {
        System.err.println("Parent doing method1");
    }
}

public class Child extends Parent {
    public void method1() {
        System.err.println("Child doing method1");
    }    
}

现在运行以下代码:

CanDoMethod1 instance = new Parent();
instance.method1();

输出是什么?

当你跑步时:

CanDoMethod1 instance = new Child();
instance.method1();

那么输出是什么?

当你跑步时:

Parent instance = new Child();
instance.method1();

那么输出是什么? 为什么这里不需要演员?

当你跑步时:

Child instance = (Child) new Parent();
instance.method1();

这会编译吗? 如果是这样,那么输出是什么?

总之,请注意所调用的方法始终是您创建的实现类的方法,无论您将其投射或分配给它。