課程:物件導向程式設計的概念
如果你之前從未使用過物件導向程式語言,在編寫程式碼前你將需要學習一些基本的概念。這個課程將介紹物件(Object),類(Class),繼承(inheritance),介面(interface)和包(packages)。討論的重點在於這些概念如何與現實世界相關聯,同時介紹了Java程式語言的語法。
- 何為物件?
- 何為類?
- 何為繼承?
- 何為介面?
- 何為包?
何為物件(Object)?
物件是理解物件導向技術的關鍵。環顧四周,你會發現很多現實世界中的物件:小狗,桌子,電視機,自行車。
現實世界中的物件具有兩個特徵:它們都擁有狀態和行為。小狗具體狀態(名字,毛色,品種,飢餓狀況)和行為(吠叫,挑逗,搖尾巴)。自行車也擁有狀態(當前的齒輪,當前的踏板節奏、當前的速度)和行為(換齒輪,剎車,提速)。通過識別真實物件的狀態和行為來學習物件導向程式設計不失為一種很好的方法。
現在就花一分鐘觀察一下你周圍的現實世界,對於你看的到所有物件,問自己兩個問題:這個物件可能處於什麼狀態?這個物件可能執行什麼行為。一定要寫下你的觀察結果。你會注意到現實世界中的物件是非常複雜的;你的桌燈可能僅有兩種狀態(開和關)和兩種行為(開燈和關燈),但是你的桌面收音機可能有更多的狀態(開、關、當前音量、當前頻段)和行為(開機,關機,增大音量,減小音量,調頻等等)。你還可能注意到,有些物件甚至還包含其他物件。現在將這些現實世界的觀察都轉化為物件導向程式設計的世界。
方法操作物件的內部狀態,並作為物件到物件通訊的主要機制。隱藏內部狀態並要求所有互動都通過物件的方法來執行,這就是所謂的資料封裝--物件導向程式設計的基本原則 舉個關於自行車的例子: 通過指定狀態(當前速度、當前齒輪型號等)並提供更改該狀態的方法,物件仍然控制著外部世界如何使用它。舉個例子:如果自行車僅有6個齒輪,改變齒輪的方法將拒絕任何小於1或者大於6的值。
將程式碼捆綁到單個軟體物件中提供了許多好處,其中包括:
- 模組性:物件的原始碼可以獨立於其他物件的原始碼來編寫和維護,一旦建立了物件,就可以在系統中輕鬆地傳遞物件
- 封裝性:通過只與物件的方法互動,其內部實現的細節對外部世界仍然是隱藏的
- 程式碼易複用:如果已經存在一個物件(可能是其它開發人員編寫的),則可以在你自己的程式中使用它。 這允許技術專家實現/測試/除錯複雜的、特定任務的物件,然後您可以信任這些物件在您自己的程式碼中執行
- 外掛化並易於除錯:如果某個特定物件出現問題,你可以方便的在應用中移除並用另外的物件來替代。這類似於解決現實世界中的機械問題,如果一個螺栓壞了,你僅需要更換螺栓,而不是整個機器
何為類(Class)?
在真實世界中,你會發覺許多獨立的物件屬於同一種類。世界上可能還有成千上萬輛自行車,它們的製造工藝和模型都一樣。每輛自行車都是由一套相同的藍圖建造而成,因此包含相同的元件。從物件導向的角度出發:我們認為自行車是自行車類的一個例項物件,類是建立單個物件的藍圖。
下面的自行車類是自行車的一種可能實現:
class Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
複製程式碼
Java程式語言的語法對於您來說可能略顯生澀,但是這個類的設計是基於前面對自行車物件的討論得來的。
欄位cadence, speed和gear代表物件的狀態,方法(changeCadence, changeGear, speedUp等)定義了它與外部世界的互動。
你可能注意到這個自行車類沒有包含主方法。這是因為這不是一個完整的應用程式。建立和使用新自行車物件的職責屬於應用程式中的其他類
下面是一個BicycleDemo類,它建立兩個單獨的Bicycle物件並呼叫它們的方法
class BicycleDemo {
public static void main(String[] args) {
// Create two different
// Bicycle objects
Bicycle bike1 = new Bicycle();
Bicycle bike2 = new Bicycle();
// Invoke methods on
// those objects
bike1.changeCadence(50);
bike1.speedUp(10);
bike1.changeGear(2);
bike1.printStates();
bike2.changeCadence(50);
bike2.speedUp(10);
bike2.changeGear(2);
bike2.changeCadence(40);
bike2.speedUp(10);
bike2.changeGear(3);
bike2.printStates();
}
}
複製程式碼
這個測試的輸出列印出兩輛自行車的踏板的節奏、速度和齒輪:
cadence:50 speed:10 gear:2
cadence:40 speed:20 gear:3
何為繼承?
不同的物件往往有相同的組成部分。例如,山地自行車、公路自行車和雙人自行車都具有自行車的特性(當前的速度、當前的踏板節奏、當前的齒輪)。然而各自又擁有不同的附加特性:
- 雙人自行車有兩個座位和兩組車把
- 公路自行車有落地式車把
- 一些山地自行車有一個額外的鏈環,給他們一個較低的傳動比 、
物件導向程式設計允許類從其他類繼承通用的狀態和行為,在這個例子中,自行車成為了山地車、公路自行車和雙人自行車的父類。在Java程式語言中,所有的類只允許有一個直接父類,而父類可以有無限的子類:
這個語法建立了一個簡單的子類,在類宣告的開頭,使用extends關鍵字,後面指明要繼承的類的名稱class MountainBike extends Bicycle {
// new fields and methods defining
}
複製程式碼
這賦予了山地車與自行車相同的欄位和方法,同時允許它的程式碼只關注其自身獨一無二的特性。這使得子類更易閱讀。然而,你必須注意在父類中定義的的欄位和方法,因為這部分程式碼不會出現在子類的原始檔中
何為介面?
正如您已經瞭解到的,物件通過它們公開的方法定義它們與外部世界的互動;例如,電視機前面的按鈕是你和塑料外殼另一邊的電線之間的介面。你按下電源鍵來開關電視機。
在其最常見的形式中,介面是一組沒有方法體的相關方法,自行車的行為(如果指定為介面),可能為如下所示
interface Bicycle {
// wheel revolutions per minute
void changeCadence(int newValue);
void changeGear(int newValue);
void speedUp(int increment);
void applyBrakes(int decrement);
}
複製程式碼
要實現這個介面,您的類的名稱將更改(例如,更改為特定品牌的自行車,例如ACMEBicycle),並且您將在類宣告中使用implements關鍵字:
class ACMEBicycle implements Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
// The compiler will now require that methods
// changeCadence, changeGear, speedUp, and applyBrakes
// all be implemented. Compilation will fail if those
// methods are missing from this class.
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
複製程式碼
實現介面允許類對其承諾提供的行為變得更加正式,介面成為類與外部世界之間的契約,編譯器在構建時強制執行這個契約。如果某個類宣告實現了某個介面,那麼該介面定義的所有方法必須出現在其原始碼中,然後該類才會成功編譯。
注意: 要實際編譯ACMEBicycle類,需要在實現的介面方法的開頭新增public關鍵字,其中緣由會在之後的課程中講述。
何為包(Package)?
包是一個名稱空間,包含一組相關的類和介面。從概念上講,您可以認為包類似於計算機上的不同資料夾。你可能將HTML頁面放在一個資料夾,圖片放在另外一個資料夾,script指令碼在另外一個。因為Java程式語言編寫的軟體應用可能包含成千上萬個獨立的類,將相關的類和介面放在不同的包中是有意義的。
Java平臺提供一個龐大的類庫(一組包)供您在自己的應用中使用,稱之為API。這些包提供較為通用的功能,例如:String物件包含字串的狀態和行為,File物件允許程式更方便的建立、刪除、查閱、比較或修改檔案系統中的檔案;Socket物件允許建立一個用於網路通訊的socket連線;不同的GUI物件控制按鈕、核取方塊和任何圖形相關的元件。有成千上萬的類可供選擇。這些保證程式設計師關注特定應用程式的設計,而不是工作所需的基礎設施
“Java平臺API規範”包含Java SE平臺提供的所有包、介面、類、欄位、方法的完整清單。作為一個程式設計師,在瀏覽器中載入該頁面並將其新增書籤,它將成為您最重要的參考文件