《java編程思想》多態與介面

向上轉型
  定義:把某個對象的引用視為對其基類類型的引用的做法被稱為向上轉型
方法調用綁定
  將一個方法調用同一個方法主體關聯起來被稱作綁定。
  前期綁定:程式執行前進行的綁定叫做前期綁定,前期綁定也是java中默認的綁定方式
  後期綁定(動態綁定或運行時綁定):在運行時根據對象的類型進行綁定。在java中除了static方法和final方法之外,其他所有的方法都是後期綁定,也就是說,通常情況下,我們不用判斷是否應該進行後期綁定,它會自動發生。
構造器和多態

  構造器調用順序:

  (1) 調用基類構造器,此步驟會不斷反覆遞歸下去,首先是構造這種層次結構的根,然後是下一層導出類,一直到最低層的導出類

  (2) 按聲明順序調用成員的初始化方法。

  (3) 調用導出類構造器的主體    

  父類(靜態變數、靜態初始化塊)>子類(靜態變數、靜態初始化塊)>
  父類(變數、初始化塊)>父類構造器>子類(變數、初始化塊)>子類構造器。(變數和初始化塊按定義順序初始化)    
構造器內部的多態方法的行為

  構造器調用的層次結構帶來一個有趣的兩難問題,如果在一個構造器的內部調用正在構造的對象的某個動態綁定方法,會發生什麼情況呢?眾所周知,在一般的方法內部,動態綁定的調用是在運行時才決定的,因為對象無法知道它是屬於方法所在的類,還是屬於那個類的導出類。如果調用構造器內部的一個動態綁定方法,就要用到那個方法的被覆蓋後的定義。這個調用的效果相當難預料,因為被覆蓋的方法在對象被完全構造之前就會被調用,這可能會造成一些難於發現的錯誤。

  

 1 public class Test {   2   3     public static void main(String[] args) {   4         new RoundGlyph(5);   5     }   6 }   7 class Glyph{   8     void draw(){ System.out.println("Glyph.draw()"); }   9     Glyph(){  10         System.out.println("Glyph before draw()");  11         draw();  12         System.out.println("Glyph after draw()");  13     }  14 }  15 class  RoundGlyph extends Glyph{  16     private int radius = 1;  17     RoundGlyph(int r){  18         radius = r;  19         System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);  20     }  21     void draw(){ System.out.println("RoundGlyph.draw(), radius = " + radius); }  22 }

  程式碼運行結果:

  

   結果是不是和你預想的結果不太一樣,嘿嘿,不用急,我們來分析一下程式碼是怎麼變成這樣的。首先在main方法中new了一個RoundGlyph類,然後類載入器發現它繼承了Glyph類,這時就會去載入Glyph類,運行Glyph類的構造方法,並在構造方法中調用draw()方法,但是這個方法在導出類中被覆蓋了,所以此時會調用子類的draw()方法,注意!關鍵來了,程式碼運行到這的時候只是載入了子類,並沒有給子類中的radius變數進行初始化,現在radius的值只是java默認分配的一個初始值,當父類運行draw()方法時,它的值只是初始值,所以這個時候會輸出0。

  因此我們得出一個驚喜的結論:當我們在基類的構造器內調用了某個方法,並且該方法被導出類所覆蓋,此時調用的是導出類內的方法而不是基類本身的方法。

  對於前面的初始化順序我們應該更正一下:

  (1) 在其他任何事物發生之前,將分配給對象的存儲空間初始化成二進位的零

  (2) 調用基類構造器

  (3) 按照聲明的順序調用成員的初始化方法

  (4) 調用導出類的構造器主體

  最後: 編寫構造器有一條有效的準則:用儘可能簡單的方法使對象進入正常狀態,如果可以的話,避免調用其他方法。

抽象類和抽象方法

  抽象類:通用介面建立起一種基本形式,以此表示所有導出類的共同部分

  抽象方法:僅有聲明而沒有方法體的方法。

  包含抽象方法的類叫做抽象類,如果一個類包含一個或者多個抽象方法,那麼該類必須被限定為抽象的。

  介面:interface關鍵字使抽象的概念更向前邁進了一步,abstract關鍵字允許人們在類中創建一個或多個沒有任何定義的方法,但是沒有提供任何相應的具體實現,這些實現是由此類的繼承者創建的。interface關鍵字產生一個完全抽象的類,它根本沒有提供任何具體實現,介面只提供了形式,不提供任何具體實現。