2017-05-06 93 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()