Java 多型 後連結(late binding)與前連結(early binding) 向上轉型(upcast)
使用過面向物件程式設計(OPP)的都知道,多型是OPP的一個主要特性之一。Java做為一種OPP語言,其也有多型特性。
那麼什麼是多型呢?
多型
指允許不同類的物件對同一訊息做出響應。即同一訊息可以根據傳送物件的不同而採用多種不同的行為方式。(傳送訊息就是函式呼叫)
先舉個例子,我們定義Shape類,Square和Circle繼承Shape類,並重載其draw方法。
public class Shape {
public void draw() {
System.out.println("draw in Shape!");
}
}
class Square extends Shape {
public void draw() {
System.out.println("draw in Square!");
}
}
class Circle extends Shape {
public void draw() {
System.out.println("drwa in Circle!");
}
}
測試程式碼如下,
public static void main(String[] args) {
Shape square = new Square();
square.draw();
Shape circle = new Circle();
circle.draw();
}
測試結果為,
draw in Square!
drwa in Circle!
以上程式碼就涉及到多型現象。當我們呼叫draw方法時,Java會根據執行時物件的型別來判斷呼叫誰的方法。比如square在執行時是Square型別,就會呼叫其draw方法;circle也類似。
或許你會疑問,square的型別命名是Shape,為什麼能賦值為Square型別的呢。這就是向上轉型了。
向上轉型(upcast)
繼承最重要的不是給子類提供了方法,而是父類與子類的關係。該關係可以概括為子類是父類的一種(The new class is a type of the existing class)。
由於繼承意味著,父類的方法,在子類中也存在,所以向父類傳送的訊息(父類的方法呼叫),也可以傳送給子類。
這樣我們可以理解,Shape square = new Square();該語句為什麼可以通過編譯。
另外,向上轉型是安全的,這是由於,向上轉型是由特定的類轉為一般的類。也就是,子類是父類的超級(superset),子類包含所有父類的方法。
後連結(late binding)
上面提到Java會根據執行時物件的型別來判斷呼叫的方法,這就是後連結。與連結接相對的是,前連結。
將方法與方法的物件聯絡起來叫連結。在程式執行前完成連結的(由編譯器或連結器完成),叫前連結,C語言就是一個例子。
然而,Java中,由於多型,在編譯的時候,編譯器僅僅知道一個引用,無法知道呼叫哪個方法。後連結解決了該問題,在執行時根據物件的型別來連結方法。後連結也稱為動態連結(dynamic binding)、執行時連結(run-time binding)。
Java中,所有的方法都是後連結,除非,該方法宣告為final方法。很容易理解,因為final方法無法被重寫,所以編譯器可以知道該方法屬於哪個型別。