基本理論
一項由Deborah J. Armstrong進行的長達40年之久的計算機著作調查顯示出了一系列面向對象程式設計的基本理論。它們是:
類
類(Class)定義了一件事物的抽象特點。通常來說,
類定義了事物的屬性和它可以做到的(它的行為)。舉例來說,“狗”這個類會包含狗的一切基礎特徵,即所有“狗”都共有的特徵或行為,例如它的孕育、毛皮顏色和吠叫的能力。類可以為程式提供模版和結構。一個類的方法和屬性被稱為“
成員”。 我們來看一段
偽代碼:
類 狗開始公有成員: 吠叫():私有成員: 毛皮顏色: 孕育:結束//Java示例:public class Dog{ public void bark(){ //... } private String colorOfFur; private boolean breed;}
在這串代碼中,我們聲明了一個類,這個類具有一些狗的基本特徵。關於公有成員和
私有成員,請參見下面的繼承性一節。
對象
對象(Object)是類的
實例。例如,“狗”這個類列舉狗的特點,從而使這個類定義了世界上所有的狗。而萊絲這個對象則是一條具體的狗,它的屬性也是具體的。狗有皮毛顏色,而萊絲的皮毛顏色是棕白色的。因此,萊絲就是狗這個類的一個實例。一個具體對象屬性的值被稱作它的“狀態”。(系統給對象分配記憶體空間,而不會給類分配記憶體空間。這很好理解,類是抽象的系統不可能給抽象的東西分配空間,而對象則是具體的。)
假設我們已經在上面定義了狗這個類,我們就可以用這個類來定義對象:
定義萊絲是狗萊絲.毛皮顏色:棕白色萊絲.吠叫()Dog lars
我們無法讓狗這個類去吠叫,但是我們可以讓對象“萊絲”去吠叫,正如狗可以吠叫,但沒有具體的狗就無法吠叫。
類和對象就好比是“實型”和“1.23”,“實型”是一種數據的類型,而“1.23”是一個真正的“實數”(即對象)。所有的“實數”都具有“實型”所描述的特徵,如“實數的大小”,系統則分配記憶體給“實數”存儲具體的數值。
訊息傳遞
一個對象通過接受訊息、處理訊息、傳出訊息或使用其他類的方法來實現一定功能,這叫做訊息傳遞機制(Message Passing)。
如:萊絲可以通過吠叫引起人的注意,從而導致一系列的事發生。
繼承
繼承性(Inheritance)是指,在某種情況下,一個類會有“子類”。子類比原本的類(稱為父類)要更加具體化。例如,“狗”這個類可能會有它的子類“牧羊犬”和“吉娃娃犬”。在這種情況下,“萊絲”可能就是牧羊犬的一個
實例。子類會繼承父類的屬性和行為,並且也可包含它們自己的。我們假設“狗”這個類有一個方法(行為)叫做“吠叫()”和一個屬性叫做“毛皮顏色”。它的子類(前例中的牧羊犬和吉娃娃犬)會繼承這些成員。這意味著程式設計師只需要將相同的代碼寫一次。
在偽代碼中我們可以這樣寫:
類牧羊犬:繼承狗定義萊絲是牧羊犬萊絲.吠叫() /* 注意這裡調用的是狗這個類的吠叫方法。*/public class Shepherd extends Dog{ }Shepherd shep = new Shepherd();shep.bark();
回到前面的例子,“牧羊犬”這個類可以繼承“毛皮顏色”這個屬性,並指定其為棕白色。而“吉娃娃犬”則可以繼承“吠叫()”這個方法,並指定它的音調高於平常。子類也可以加入新的成員,例如,“吉娃娃犬”這個類可以加入一個方法叫做“顫抖()”。設若用“牧羊犬”這個類定義了一個實例“萊絲”,那么萊絲就不會顫抖,因為這個方法是屬於吉娃娃犬的,而非牧羊犬。事實上,我們可以把繼承理解為“是”或“屬於”。萊絲“是”牧羊犬,牧羊犬“屬於”狗類。因此,萊絲既得到了牧羊犬的屬性,又繼承了狗的屬性。 我們來看偽代碼:
類吉娃娃犬:繼承狗開始公有成員: 顫抖()結束類牧羊犬:繼承狗定義萊絲是牧羊犬萊絲.顫抖() /* 錯誤:顫抖是吉娃娃犬的成員方法。 */
當一個類從多個父類繼承時,我們稱之為“
多重繼承”。如一隻狗既是吉娃娃犬又是牧羊犬(雖然事實上並不合邏輯)。多重繼承並不總是被支持的,因為它很難理解,又很難被好好使用。
封裝性
具備封裝性(Encapsulation)的面向對象程式設計隱藏了某一方法的具體執行步驟,取而代之的是通過訊息傳遞機制傳送訊息給它。因此,舉例來說,“狗”這個類有“吠叫()”的方法,這一方法定義了狗具體該通過什麼方法吠叫。但是,萊絲的朋友並不知道它到底是如何吠叫的。
封裝是通過限制只有特定類的對象可以訪問這一特定類的成員,而它們通常利用接口實現訊息的傳入傳出。舉個例子,接口能確保幼犬這一特徵只能被賦予狗這一類。通常來說,成員會依它們的訪問許可權被分為3種:公有成員、
私有成員以及保護成員。有些語言更進一步:Java可以限制同一包內不同類的訪問;
C#和
VB.NET保留了為類的成員聚集準備的關鍵字:internal(C#)和Friend(VB.NET);
Eiffel語言則可以讓用戶指定哪個類可以訪問所有成員。
多態
多態(Polymorphism)是指由繼承而產生的相關的不同的類,其對象對同一訊息會做出不同的回響。例如,狗和雞都有“叫()”這一方法,但是調用狗的“叫()”,狗會吠叫;調用雞的“叫()”,雞則會啼叫。 我們將它體現在偽代碼上:
類狗開始公有成員: 叫() 開始 吠叫() 結束結束類雞開始公有成員: 叫() 開始 啼叫() 結束結束定義萊絲是狗定義魯斯特是雞萊絲.叫()魯斯特.叫()
這樣,雖然同樣是做出叫這一種行為,但萊絲和魯斯特具體做出的表現方式將大不相同。多態性的概念可以用在
運算符重載上,本文不再贅述。
抽象性
抽象(Abstraction)是簡化複雜的現實問題的途徑,它可以為具體問題找到最恰當的類定義,並且可以在最恰當的繼承級別解釋問題。舉例說明,萊絲在大多數時候都被當作一條狗,但是如果想要讓它做牧羊犬做的事,你完全可以調用牧羊犬的方法。如果狗這個類還有動物的父類,那么你完全可以視萊絲為一個動物。
名詞釋意
編程范型 對於OOP的準確定義及其本意存在著不少爭論。
通常,OOP被理解為一種將程式分解為封裝數據及相關操作的模組而進行的編程方式。有別於其它編程方式,OOP中的與某數據類型相關的一系列操作都被有機地封裝到該數據類型當中,而非散放於其外,因而OOP中的數據類型不僅有著狀態,還有著相關的行為。OOP理論,及與之同名的OOP實踐相結合創造出了新的一個編程架構;OOP思想被廣泛認為是非常有用的,以致一套新的
編程范型被創造了出來。(其它的編程范型例如函式式編程或過程式編程專注於程式運行的過程,而邏輯編程專注於引發程式代碼執行的斷言)
對面向模擬系統的語言(如:SIMULA 67)的研究及對高可靠性系統架構(如:高性能作業系統和CPU的架構)的研究最終導致了OOP的誕生。