之前介紹過了型別,但是都是已經定義好的型別,如整數(Int)、字串(String)等等…,現在要介紹如何自己定義新的型別,怎麼定義新的型別呢?可以使用類別(class)、結構(struct)與列舉(enum)的方式定義新的型別。那現在就要先說明一下類別(class),而為什麼要先介紹類別(class)呢?因為物件(object)就是經由類別(class)所建立的實體(instance)。
類別(class)可以說是建造物件(object)的藍圖,例如汽車設計圖是一個類別(class),因此可以使用汽車設計圖這類別(class),產生汽車的物件(object),例如產生了一台跑車,這跑車就是一個物件(object),而說到類別(class)就要先了解屬性(property)與方法(method),簡單的說屬性(property)就是類別(class)內的變數或常數,而方法(method)就是類別(class)內的函式(function)。
了解類別(class)後,那就看看如何定義吧,下面就是一個沒有屬性(property)與方法(method)的類別,用class開頭,加上類別名稱最後再接上{}。而類別名稱就是型別名稱,因此當你定義新的類別(class)也就是等於發明新的型別一樣,所以要注意類別名稱的開頭需要大寫,就像整數(Int)一樣。
class + 類別名稱 + { + }
那如何建立一個物件(object)呢?其實方法很簡單,就跟呼叫函式(function)很像,就是要加上小括弧()。
var + 變數名稱 = 類別名稱 + ()
let + 常數名稱 = 類別名稱 + ()
而用類別(class)建立的東西就是物件(object),所以像下面的suvCar與coupCar就是兩個物件(object)。而整數(Int)是用結構(struct)所建立的,因此所產生的並不是物件(object)。現在你或許還不知道什麼是結構(struct),但是沒關係,之後會在介紹結構(struct)與列舉(enum)。
屬性(property)
上面看到的Car是沒有屬性(property)與方法(method)的類別,所以接下來要介紹如何加入屬性(property),其實就是在類別(class)的大括號{}內宣告變數(var)或是常數(let)。
這邊有一點非常重要,就是一定要初始化物件(object)的屬性(property),如果沒有初始化會顯示錯誤,如剛剛的屬性brand沒有初始化,則會顯示下面的錯誤。
有三種方法讓每個屬性有初始值:
- 宣告屬性(property)時給初始值。
- 宣告屬性(property)為optional,因為設為optional,預設為nil。
- 定義物件(object)的初始化方法(initializer)。
上面因該只有initializer不知道是什麼?而initializer算是方法(method),所以等一下在介紹過方法(method)之後再說明什麼是initializer。
那如何存取物件(object)的屬性(property)呢?其實很簡單,建立物件(object)之後,在儲存物件(object)的變數(var)或常數(let)後加上.與屬性(property)名稱就可以存取物件的屬性。
讀取:
變數名稱/常數名稱 + . + 屬性名稱存入:
變數名稱 + . + 屬性名稱 = 新的值
『範例說明』
1 - 4 : 宣告了ㄧ個Car的類別(class)。
2 : 宣告了ㄧ個常數,常數名稱為brand的屬性,型別為字串,初始值為”Lexus”。
3 : 宣告了ㄧ個變數,變數名稱為capacityOfTank的屬性,型別為整數,初始值為0。
6 : 使用類別Car建立一個物件(object)並將物件(object)指定給變數suvCar,所以suvCar為一個物件(object)。。
7 : 使用類別Car建立一個物件(object)並將物件(object)指定給變數coupeCar,所以coupeCar為一個物件(object)。
9 : 呼叫suvCar的brand屬性。
10 : 修改coupeCar的capacityOfTank屬性的值為50。
方法(method)
接下來要介紹如何加入方法(method),其實就是在類別(class)的大括號{}內加入函式(function)。簡單說在類別(class)內的函式(function)就是方法(method)。
『範例說明』
1 - 12 : 宣告了ㄧ個Car的類別(class)。
2 : 宣告了ㄧ個常數,常數名稱為brand的屬性,型別為字串,初始值為”Lexus”。
3 : 宣告了ㄧ個變數,變數名稱為capacityOfTank的屬性,型別為整數,初始值為0。
5 - 7 : 宣告了ㄧ個函式,函式名稱為parking。
9 - 11: 宣告了ㄧ個函式,函式名稱為drive,並有傳入參數number。
所以看到上面知道如何建立方法(method)了,那如何使用呢?其實跟屬性(property)很像,一樣是透過.來呼叫方法(method)。而且在方法(method)內也可以存取自己的屬性(property)。
變數名稱/常數名稱 + . + 方法名稱 + ( + 參數 + )
『範例說明』
1 - 16 : 宣告了ㄧ個Car的類別(class)。
2 : 宣告了ㄧ個常數,常數名稱為brand的屬性,型別為字串,初始值為”Lexus”。
3 : 宣告了ㄧ個變數,變數名稱為capacityOfTank的屬性,型別為整數,初始值為0。
5 - 7 : 宣告了ㄧ個函式,函式名稱為parking。
9 - 11: 宣告了ㄧ個函式,函式名稱為drive,並有傳入參數number。
13 - 15 : 宣告了ㄧ個函式,函式名稱為fileUp,並將屬性capacityOfTank的值改為50。
18 : 使用類別Car建立一個物件(object)並將物件(object)指定給變數suvCar,所以suvCar為一個物件(object)。。
19 : 使用類別Car建立一個物件(object)並將物件(object)指定給變數coupeCar,所以coupeCar為一個物件(object)
20 : 呼叫suvCar的方法parking,印出“停車”。
21 : 呼叫coupeCar的方法drive,並傳入2,印出“目前是D2”。
22 : 呼叫coupeCar的方法fileUp,看到原先21行時屬性capacityOfTank為0,在呼叫fileUp方法後,屬性capacityOfTank修改為50。
initializer
接下來說明一下剛剛沒說明的initializer,當物件(object)被建立出來時,該物件(object)的initializer將會被呼叫,所以可以在initializer內將屬性(property)初始化。initializer是一個特殊的函式(function),因為initializer這函式(function)名稱是固定的,名稱為init,而且宣告時不需要加上func,當建立物件(object)時,會自動被呼叫,最後就是在類別(class)內可以定義多個init,名稱都一樣,都是init,但是接收的參數需要不同。所以在建立物件(object)時會因為傳入的參數不同,去找對應的init。
『範例說明』
1 - 13 : 宣告了ㄧ個Car的類別(class)。
2 : 宣告了ㄧ個變數,變數名稱為brand的屬性,型別為字串。
3 : 宣告了ㄧ個變數,變數名稱為capacityOfTank的屬性,型別為整數。
5 - 8 : 宣告了init,此init沒有傳入參數,將屬性brand設定為”Lexus”,屬性capacityOfTank設定為0。
9 - 13: 宣告了init,此init有傳入參數,分別為型別為字串的brand與型別為整數的capacityOfTank,在這裡看到10與11行都有加上self,因為傳入參數名稱與屬性名稱相同,所以加上self.來指名是屬性的變數。
15 : 使用類別Car建立一個物件(object)並將物件(object)指定給變數suvCar,所以suvCar為一個物件(object)。 因為在建立時沒傳入參數,因此是呼叫第5行的init,所以brand為”Lexus”而capacityOfTank為0。
16 : 使用類別Car建立一個物件(object)並將物件(object)指定給變數coupeCar,所以coupeCar為一個物件(object) 。因為在建立時傳入參數(brand: “BMW”, capacityOfTank: 50),因此是呼叫第9行的init,所以brand為”BMW”而capacityOfTank為50。
因為物件(object)建立時會呼叫initializer,因此如果沒有自己寫initializer,就會呼叫default的initializer,而default的initializer是自動生成的,所以default的initializer會將屬性設為當初宣告的初始值,因此當屬性(property)有初始值時,會自動生成default的initializer。
最後就是要說一下,其實物件(object)內的屬性(property)與方法(method)的回傳值,也可以是物件(object),而存取的方式也是加上.就可以。
『範例說明』
1 - 3 : 宣告了ㄧ個CarBrand的類別(class),裡面有一個變數名稱為brand的屬性。
5 - 11 : 宣告了ㄧ個Car的類別(class),裡面有一個變數名稱為brand的屬性與一個getBrand()的函式,而brand是一個物件(object),是由CarBrand這類別(class)所建立的,而getBrand()的函式則是回傳一個CarBrand物件(object)。
13 : 宣告了ㄧ個變數,變數名稱為suvCar的物件(object),這物件(object)是由Car這類別(class)所建立的。
14 : 呼叫suvCar的屬性brand。
15 : 呼叫suvCar方法getBrand()內的屬性brand。
補充說明一下在類別(class)內屬性(property)與方法(method)的順序不重要,誰在前面都可以。