機
器
人
構建式
這個章節的重點,在於帶領讀者理解物件導向的概念,而非介紹單一個程式語法。此章節的程式語法和 JavaScript 等程式語言相近,但並非任何真實程式語言。請專注於章節中的概念部分,而非語法部分。
讓我們接續下區剛剛杯子的例子。每一個杯子都有自己獨特的地方,例如顏色、容量、高度等。我們可以建立一個類別,叫做「杯子」,用之建立許多物件並將其定義作我們想要的杯子。
類別 杯子{
}
假設現在我們要設計一個高度為 10cm,容量 300ml,顏色紅色的杯子,我們可以呼叫杯子類別,建立一個杯子物件:
cup = 杯子();
cup.height = 10;
cup.volume = 300;
cup.color = "red";
如此一來,我們便建立了一個我們想要的杯子物件。但是,每一次都這樣寫,會不會有一點點太麻煩呢?現在我們用了四行程式才完成,那麼有沒有更快的方法呢?或許我們可以在建立物件時,就設定好杯子的高度、容量、體積?
「this」的概念
我們先來舉另外一個例子。假設我們現在要建立一個「建築」類別,裡面有各種不同種類的建築。接著我們要建立300棟建築的物件,講他們出存在 building1~300 的變數中。然而,這300棟建築都有一個特點,那就是它們都以水泥建成。我們可以寫說:
類別 建築{
}
接著:
building1 = 建築();
building1.material = "水泥";
building2 = 建築();
building2.material = "水泥";
.
.
.
building299 = 建築;
building299.material = "水泥";
building300 = 建築;
building300.material = "水泥";
但是如果每次都這樣寫,我們豈不是把自己累死?建立300個物件,並不代表要設定300次物件的屬性呀!既然我們一開始就知道所有建築物都會有 material = "水泥"
這件事,其實我們可以在建立類別時就設定的。如下:
類別 建築{
這個.material = "水泥";
}
接著,我們只需要建立那些建築,而且那些建築就會自帶有 material = "水泥"
的屬性:
building1 = 建築();
building2 = 建築();
.
.
.
building300 = 建築();
此時,我們就能印出 building1
的 material
屬性了:
print(building1.material);
/* 將會印出:“水泥” */
讓我們仔細再看看剛才的程式:
類別 建築{
這個.material = "水泥";
}
值得注意的是,我們並沒有直接說 material = "水泥"
,反而是 這個.material = "水泥"
。請問這是為什麼呢?
記得之前說過的,在物件導向的世界裡,.
所代表的,就是中文的「的」。在宣告類別的時候,藉由使用 這個.
,我們等同於是正在告訴電腦 material
是「建築類別」的屬性之一。
在許多真實的程式語言中, 這個
是用關鍵字 this
或 self
來表達。
建構函數
讓我們回到一開始的問題:如何在建立杯子物件時,同時設定這個杯子的顏色、容量、高度?答案很簡單,我們應該要使用所謂的建構函數。
我們可以重新寫宣告一次杯子類別:
類別 杯子{
建構(col, vol, hei){
這個.color = col;
這個.volume = vol;
這個.height = hei;
}
}
而在建立杯子物件時,應該這樣寫:
cup1 = 杯子("red", 300, 10);
你可能會覺得很奇怪,為什麼杯子後面的括號裡可以放入這些東西。答案也很簡單: "red"
將會對應到建構裡的 col
變數, 300
將對應到 vol
變數,而 10
將對應到 hei
變數。
接著就到了建立物件的時候了,電腦在建立一個物件時,會自動搜尋類別中成為「建構」的函數,因此可以說,建立一個物件,就是呼叫一次建構函數。
在建構函數中,我們可以看到三行程式,分別將 這個.color
、 這個.volume
、 這個.height
設定為 col
、vol
、hei
。
最後,我們可以嘗試印出 cup1
的屬性,看看是否這些屬性都成功地被設定了:
print(cup1.color);
/*印出:red*/
print(cup1.volume);
/*印出:300*/
print(cup1.height);
/*印出:10*/