物件導向的三種基本特徵:資料抽象、繼承和多態。
資料抽象即抽象資料類型(abstract data type, ADT),這其中包含三層含義:封裝、資訊/實現隱藏和狀態保持(參加blog:Java-物件導向含義)。
多態通過分離“做什麼”和“怎麼做”(可以有多種方法實現“怎麼做”,這也是之所以稱為多態的原因),從另一角度將介面和實現(or基類與子類or子類與子類)分離開來。
ps:實際上“基類和子類”也可以理解成是“介面和實現”的關係。
“封裝”通過合并特徵和行為來建立新的資料類型;“實現隱藏”則通過將細節私人化(private)把介面和實現分離開來;而多態的作用則是消除類型之間的耦合關係(即使不同類中的同一方法彼此間沒有耦合關係,參加blog:Java-物件導向含義 求多邊形面積的例子)。
繼承允許將對象視為它自己本身的類型或其基底類型來加以處理。這種能力極為重要,因為它允許將多種類型(從同一基類匯出的)視為同一類型來處理。而同一份代碼也就可以毫無差別地運行在這些不同類型之上了。多態方法允許一種類型表現出與其他相似類型之間的區別(即對同一實現目標在實現方法上的區別,這種區別是根據方法行為的不同而表現出來的),只要它們都是從同一基類匯出的。
再論向上轉型
對象既可以作為它自己本身的類型使用,也可以作為它的基類使用。這種把對某個對象的引用視為對其基類的引用的做法稱為“向上轉型”。
/** *//**
* Title: Notes to play on musical instruments<br>
* Description: 此例解釋"向上轉型"概念, 無任何功能介面<br>
* Company: Augmentum Inc<br>
* Copyright: (c) 2008 Thinking in Java<br>
* @author Forest He
* @version 1.0
*/
package com.augmentum.foresthe;
class Note ...{
private String noteName;
private Note (String noteName)...{ this.noteName = noteName; }
public String toStirng() ...{ return noteName; }
public static final Note
MIDDLE_C = new Note("MIDDLE_C"),
C_SHARP = new Note("C_SHARP"),
B_FLAT = new Note("B_FLAT");
}
/**//*Note類是一個枚舉類,包含固定數目的、可供選擇的不變對象。Note類外不能再產生另外的對象,因為其Constructor是私人的*/
class Instrument ...{
public void play(Note note) ...{ System.out.println("Intrument.play() " + note.toStirng()); }
}
class Wind extends Instrument ...{
public void play(Note note) ...{ System.out.println("Wind.play() " + note.toStirng()); }
}
class Music ...{
public static void tune(Instrument instrument) ...{ instrument.play(Note.MIDDLE_C); }
public static void main(String[] args) ...{
Wind flute = new Wind();
tune(flute); //Upcasting
}
}
Music.tune()方法接受一個Instrument引用,同時也接受任何匯出自Instrument的類。在main()中,當一個Wind引用傳遞到tune()方法時,就會出現這種情況,而不需要任何類型轉換(Instrument的介面必定存在於Wind中)。從Wind向上轉型為Instrument可能會“縮小”介面,但不會比Instrument的全部介面更窄。
如果讓tune()方法直接接受一個Wind引用作為自己的參數,似乎會更為直觀。但這樣引發的一個重要問題是:如果那樣做,就需要為系統內Instrument的每種類型都編寫一個新的tune()方法(例如Stringed弦樂和Brass管樂)。所以我們只接收基類作為參數,而不是匯出類。