2011-11-07 80 views
0

如果我有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的版本被调用?

+3

为什么不通过调试器运行代码并包含一些'println'语句? – mre

+1

为什么不直接在测试程序中快速实现并找出? – Tudor

+0

写一个学习测试,并找出:http://users.csc.calpoly.edu/~djanzen/tdl/learningtest/ –

回答

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() { 
     ... 
    } 
} 
+0

只要我写了评论,就看到了更新。现在我已经删除了我的评论,这一系列的评论只会让其他人感到困惑;) – DaveJohnston

3

Child#method2将被调用,因为它覆盖了父的。

+0

出于兴趣,是'Class#method'这个表示法的一个约定,用于表明它是一个实例方法而不是静态方法?因为如果有的话,这对未来的使用会很有用。 –

+0

我不知道符号有多突出,但至少这是我认为的方式:)我知道这是[ruby]中的一个标准(http://ruby-doc.org/docs/Newcomers/至少ruby.html#符号)。 – jornb87

+0

我以前见过它在这里使用过。这不是一个坏习惯,我想我也会开始使用它。 –

3

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

即使您调用Parent中定义的method1,一旦该方法调用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! 

所以选择一个基于参数类型的方法是静态完成。它不会根据运行时类型选择不同的方法。

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

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 
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(); 

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

总之,请注意,调用的方法始终是您创建的实现类的的方法,无论您将其转换或分配给什么。