2017-05-06 81 views
0

我有以下四个类。为什么这种类型的子类变量调用函数?

类注:

public class Note { 

    Pitch primaryPitch = new Pitch(); 
    static Pitch secondaryPitch = new Pitch(); 

    Note() { 
     System.out.println("Tune()"); 
    } 
    static void pitch() { 
     System.out.println("Note.pitch()"); 
    } 
    void volume() { 
     System.out.println("Note.volume()"); 
    } 
} 

类调​​:

public class Tune extends Note{ 

    Tune() { 
     System.out.println("Tune()"); 
    } 

    static void pitch() { 
     System.out.println("Tune.pitch()"); 
    } 

    void volume() { 
     System.out.println("Tune.volume()"); 
    } 

    void rhythm() 
    { 
     Note note = (Note) this; 
     note.volume(); 
    } 
} 

类歌曲:

public class Song extends Tune{ 

    void volume() { 
     System.out.println("Song.volume()"); 
     } 
    } 

类检验:

public class Test { 

    public static void main(String[] args) { 

      Note note2 = new Song(); 
      ((Tune)note2).rhythm(); 
} 

当我运行main时,我期望输出Note.volume()。我期望输出的原因是因为在Tune类中,当我调用note.volume();时,note已经被注释为Note对象,所以我期望使用Note类的volume()方法调用。相反,我得到Song.volume()这意味着我正在使用Song类的volume()方法调用。

我的问题是,为什么我得到Song.volume()而不是note.volume();

+4

如果您还没有准备好,你应该了解的多态性,因为它解释那种行为。 – 4castle

+0

由于'Song'覆盖了'volume',这就是覆盖的工作原理 - 它们通过多态方式调用实现的对象的实际运行时类型,而不是指针表达式的编译时类型。 –

回答

3

因为音符是Song()类型的对象。将其转换为父类型的事实不会更改volume()方法的多态行为。如果您运行在你的IDE代码这是显而易见的,并且在Tune.Rhythm(),看看变量值:

enter image description here

1

this意味着当前例如Song,即使你投以Note,它仍然Song例如

顺便说一下,在运行时,的Java没有类型,所以cast在运行时没有意义。 cast只是来自Compiler来推断上下文的类型。

由于SongextendsNote通过extendsTune, 和Overridevolume方法,所以this.volume()将调用OverrideSong.volume方法。

如果需要调用Note.volumeparent类,需要使用supervolume方法,如:super.volume()