繼承

  繼承觀念在物件導向程式設計中扮演著相當重要的解色,透過繼承可以讓類別所提供的功能與方法得以傳承至其他的類別中使用,同時可以讓程式的分工更加的細膩,每個類別只需負責提供一個特定的功能服務,若有其他類別需要這類的功能只需利用繼承的方式將該功能傳承下來,這點就相當類似自然界中物種的分類方式,例如:貓與老虎都是同屬於貓科動物,代表它們兩者之間都具有貓科動物的特徵,但卻又個自擁有屬於自己的習性,再以人類來說:我們身體上的一些特徵,有些可能是源自於你的上一代的特性,當然,你的父母親也是源自於他們上一代的遺傳。繼承在Java 語言中的保留字為 extends ,我們可以在宣告類別名稱的尾端利用extends關鍵字宣告此類別是繼承自那個類別,值得注意的是Java並不像C++支援多重繼承,所以每個類別最多只能繼承至一個類別,但同一個類別卻可以被許多不同類別繼承喔! 讓我們利用一個繪圖範例來說明,下表為本範中使用到的各個類別之間的功能與關係表:

程式 功能說明 繼承關係
Dot.java 繪製一個點於螢幕上
Line.java 繪製一個線於螢幕上 extend Dot
Shape.java 繪製一個形狀於螢幕上 extend Shap
DrawMain.java 主程式

【程式Dot.java】:

Dot類別位置此範例程式繼承結構中的最上層,因此所提供的是一個最基礎的功能,將一個字元(等同於一個點)繪製於螢幕上,為了增加此範例的變化性,setStyle方法可以讓我們自行定義要印出來的字元為何,若無自行定義字元圖樣,則預設輸出為*字。

//Dot.java

【程式Line.java】:

Line類別繼承至Dot類別,因此在Line類別中將可以呼叫父類別(Dot類別)所提供的方法,在drawLine()方法中,利用重覆的呼叫Dot類別的drawDot()方法繪製出我們需要長度的線條於螢幕上,其中 offset傳入參數代表的是線條的起始位置,length傳入參數代表的是線條的長度。

//Line.java

【程式Shape.java】:

Shape類別繼承至Line類別,因此在Shape類別中可以直接呼叫父類別(Line類別)所提供的方法,在這drawTriangle()方法中我們依三角型的圖形需求向Line類別呼叫繪圖多條不同長度的與起始位置的線條,最後這些線條將會排例成一個正三角型。

//Shape.java

【程式DrawMain.java】:

  DrawMain為本範例的主程式,在程式進入點main方法裡,首先將Shape類別實作成二個物件,並分別存放於triangleA與triangleB變入中,接著我們為這兩個物件分別設定二個不同的輸出字元與高度。到這裡不知讀者是否還記得前一節所介紹的類別與物件的關係,在此範例中我們利用同樣的Shape類別實作成兩個物件,隨後它們分別擁有個自的資料成員,因此到最後的輸出結果,將會有兩個截然不同的表現方式。讀者可以再重新的回想思考一下類別與物件之間的關係,相信應該很快就能有所領悟。

//DrawMain.java

【執行結果】:

2-19 繼承範例執行結果

圖 14 繼承範例執行結果

  在這個範例中我們利用了繼承結構的設計方式,由一個Dot類別開始,Dot類別只具有一個畫點的簡單功能,當我們想要為它加上畫線功能時,只需要利用利用繼承的方式讓Line類別承襲先前的Dot類別畫點方法,並在加上一個新的畫線的功能,最後Shape則可利用許多條不同長度的線條組合成一個圖樣,讀者若有興趣也可以自行在撰寫繪製其他圖樣的Shape類別(如星型、倒三角型),這時我們就不必在從新設計畫線與畫點的功能,只需將撰寫好的類別繼承至Line類別,就可以直接引用Line與Dot中所提供的方法。所以活用繼承關係可以讓程式更具有彈性與擴充性,同時也達到程式再利用的優點。

  由下圖可以更容易了解繼承結構的物件運作方式,當主程式呼叫setStyle()方法時,由於在子類別找不到該方法就會往父類別呼叫(向繼承的類別查尋是否有提供該方法),最後這個請求會傳到setStyle()方法的提供者Dot物件,同樣的,繪製圖型時也是利用繼承的階層關係,經由一層層的往上呼叫,最終會由Dot畫出點於螢幕上。Dot物件並不會知道自己要畫的是什麼樣的圖形,Line物件也只知道自己要畫的是線,只有triangleA與triangleC物件知道自己將要畫的是三角型,這這正是繼承結構最大的特色,每個物件只專注自己負責的功能,越往上層的物件愈單純,如此一來每個物件都可以相當容易進行功能上的擴充,或是重覆再利用於其他的應用程式中。

2-20 繼承範例物件意示圖

圖 15繼承範例物件運作意示圖