前兩天連續介紹了函式的基本用法,這時你一定想說,身為物件導向語言的一員,該有物件出現了吧!對,這就來了 XD
接下來這幾天會頻繁跟 Kotlin 類別 (Class) 打交道,其中會涵蓋 class
, interface
, abstract
, sealed class
, object class
, companion objects
, data class
, value class
, enum class
,讓我們先跟最輕切的 class
開始征服~
在 Kotlin 中,類別是用來定義物件 (Objects) 的樣本 (藍圖)。它們將資料 (數值) 和行為 (函式) 封裝在同一個元素中,其實 Kotlin 的原生型別也是透過這種方式被建立的,但這次挑戰賽中不會談論到這部分,有興趣的讀者可以去看看 GitHub 上 Kotlin 的專案。另外,類別也是物件導向語言用來提供了一種建模真實世界的基本元件。
要在 Kotlin 中建立一個類別,您需要使用 class
關鍵字後面跟著類別的名稱。以下是 Kotlin 中一個類別的範例:
class Person(val name: String, val age: Int) {
fun greet() {
println("你好,我叫 $name,我 $age 歲。")
}
}
在上面的範例中,我們定義了一個名為 Person
的類別,它有兩個屬性:name
和 age
。每個屬性前面的 val
關鍵字表示它們是唯讀屬性,意味著可以存取但無法修改。greet()
函式允許 Person
類別的實例自我介紹。
要建立一個 Person
類別的實例並呼叫 greet()
函式,可以這樣做:
val person = Person("John Doe", 25)
person.greet()
這將輸出:你好,我叫 John Doe,我 25 歲。
有遇過物件導向語言的讀者應該會在這裡問到,那建構子 (constructor) 呢?
建構子是用於初始化類別的特殊成員函數。建構子在創建類別的物件時被呼叫,可以用於為類的屬性設置初始值。例如上述的 name
和 age
就是 Person
的主建構子。
這時候你又會說:主?
對!在 Kotlin 裡面有分主 (primary) 跟次 (secondary),除了類別關鍵字後面的建構子外,我們也可以在類別主體內建立另一個建構子,他可以作為主建構子的擴充,用於定義更多於主建構子的行為,範例如下:
class Person(val name: String, val age: Int) {
val children: MutableList<Person> = mutableListOf()
// 可變變數用於儲存當前類別的子女物件
constructor(name: String) : this(name, 0) {
// 次建構子只使用單一的傳入變數,他會預設給 `Person` 型別年齡為 0
}
constructor(name: String, parent: Person) : this(name, 0) {
// 次建構子除了年齡為 0,他還讓這個物件可以被加入他/她父母物件的子女列表中
parent.children.add(this)
}
constructor(name: String, age: Int, parent: Person) : this(name, age) {
// 同上,但讓年齡也可以被設定
// 如果這行被註解掉,則設定父母的功能將只剩下年齡為 0 的選項
parent.children.add(this)
}
fun greet() {
println("你好,我叫 $name,我 $age 歲。")
}
}
fun main() {
// 使用主要建構子來創建 Person 物件
val person1 = Person("Alice", 30)
println("Name: ${person1.name}, Age: ${person1.age}") // 輸出:Name: Alice, Age: 30
// 使用次要建構子來創建 Person 物件
val person2 = Person("Bob")
println("Name: ${person2.name}, Age: ${person2.age}") // 輸出:Name: Bob, Age: 0
// 創建父母 Person 物件
val parent = Person("Charlie", 50)
// 使用帶有父母參數的次要建構子來創建 Person 物件
val child = Person("David", 25, parent)
// 現在 parent 物件的子女列表應該包含 child 物件
println("Parent's Children: ${parent.children.map { it.name }}") // 輸出:Parent's Children: [David]
}