泛化
在處理類型的層次結構時,經常把一個對象不當作它所屬的特定類型來對象,而是将其當作其基類的對象類對象。這稱為“泛化” ,這樣可以編寫出不依賴特定類型的代碼。
後期綁定
這将會産生一個問題,當我們将導出類型的對象當作其泛化基類型來看待時,比如我們自行車看作是交通工具,那麼仍然存在一個問題,編譯器在編譯時是不可能知道自己應該執行哪一段代碼将被執行,那對象如何會根據自身的具體類型來執行恰當的代碼?
舉個例子,在下面的圖中,BirdController對象僅僅處理泛化的Bird對象,而不了解它們的确切類型。從BirdController的角度看,這麼做非常友善,因為不需要編寫特别的代碼來判定要處理的Bird對象的确切類型或其行為。當move()方法被調用時,即便忽略Bird的具體類型,也會産生正确的行為(Goose(鵝)會走、非或遊泳,Penguin(企鵝)走或遊泳),這是如何發生的呢?

為了解決這個問題,面向對象程式設計語言使用了後期綁定的概念。當向對象發送消息時,被調用的代碼直到運作時才能确定。編譯器確定被調用方法的存在,并對調用參數和傳回值執行類型檢查,但是并不知道将被執行的确切代碼。
為了執行後期綁定,Java使用一小段特殊的代碼替代絕對位址調用。這段代碼使用在對象存儲的資訊來計算方法體的位址。這樣,根據這一小段代碼的内容,每個對象都可以具有不同的行為表現,當向一個對象發送消息時,該對象就能夠直到對這條消息應該做些什麼。在Java 中,動态綁定是預設行為,不需要添加額外的關鍵字來實作多态(C++是使用virthal關鍵字來聲明某個方法以實作後期綁定屬性所帶來的靈活性)。
向上轉型
// 編寫一個方法,這個方法可以将任何Shape類型作為參數
void doSomthing(Shape shape){
shape.erase();
//...
shape.draw();
}
複制
Circle circle = new Circle();
Triangle triangle = new Triangle();
Line line = new Line();
doSomthing(circle);
doSomthing(triangle);
doSomthing(line);
複制
對doSomthing()的調用會自動地正确處理,而不管對象的确切類型,比如
doSomthing(circle);
由于Circle可以被doSomething()看作是Shape,也就是說,doSomthing()可以發送給Shape的任何消息,Circle也可以接收。
因為發送基類的任何消息,導出類都可以接收,那麼将導出類看作是它的基類的過程稱為向上轉型。