類別
Kotlin 支援物件導向程式設計,其中包含類別與物件。物件對於在程式中儲存資料很有用。 類別允許您宣告物件的一組特性。當您從類別建立物件時,可以節省時間和精力,因為您不必每次都宣告這些特性。
要宣告一個類別,請使用 class
關鍵字:
class Customer
屬性
類別物件的特性可以在屬性中宣告。您可以為類別宣告屬性:
- 在類別名稱後的圓括號
()
內。
class Contact(val id: Int, var email: String)
- 在花括號
{}
定義的類別主體內。
class Contact(val id: Int, var email: String) {
val category: String = ""
}
我們建議您將屬性宣告為唯讀 (val
),除非在建立類別實例後需要更改它們。
您可以在圓括號內宣告不帶 val
或 var
的屬性,但這些屬性在建立實例後無法存取。
- 圓括號
()
內包含的內容稱為類別標頭。- 宣告類別屬性時可以使用尾隨逗號。
與函式參數一樣,類別屬性可以有預設值:
class Contact(val id: Int, var email: String = "[email protected]") {
val category: String = "work"
}
建立實例
要從類別建立物件,您可以使用建構函式宣告一個類別實例。
預設情況下,Kotlin 會自動建立一個帶有類別標頭中宣告參數的建構函式。
例如:
class Contact(val id: Int, var email: String)
fun main() {
val contact = Contact(1, "[email protected]")
}
在此範例中:
Contact
是一個類別。contact
是Contact
類別的實例。id
和email
是屬性。id
和email
與預設建構函式一起用於建立contact
。
Kotlin 類別可以有多個建構函式,包括您自己定義的建構函式。要了解更多關於如何宣告多個建構函式的資訊,請參閱建構函式。
存取屬性
要存取實例的屬性,請在實例名稱後加上一個句點 .
,然後寫上屬性名稱:
class Contact(val id: Int, var email: String)
fun main() {
val contact = Contact(1, "[email protected]")
// 列印屬性的值:email
println(contact.email)
// [email protected]
// 更新屬性的值:email
contact.email = "[email protected]"
// 列印屬性的新值:email
println(contact.email)
// [email protected]
}
要將屬性的值作為字串的一部分進行串聯,您可以使用字串樣板 (`). 例如:
kotlinprintln("Their email address is: ${contact.email}")
成員函式
除了將屬性宣告為物件特性的一部分之外,您還可以透過成員函式定義物件的行為。
在 Kotlin 中,成員函式必須在類別主體內宣告。要在實例上呼叫成員函式,請在實例名稱後加上一個句點 .
,然後寫上函式名稱。例如:
class Contact(val id: Int, var email: String) {
fun printId() {
println(id)
}
}
fun main() {
val contact = Contact(1, "[email protected]")
// 呼叫成員函式 printId()
contact.printId()
// 1
}
資料類別
Kotlin 具有資料類別,對於儲存資料特別有用。資料類別與類別具有相同的功能,但它們自動帶有額外的成員函式。這些成員函式允許您輕鬆地將實例列印為可讀的輸出、比較類別的實例、複製實例等等。由於這些函式是自動可用的,因此您無需花時間為每個類別編寫相同的樣板程式碼。
要宣告一個資料類別,請使用 data
關鍵字:
data class User(val name: String, val id: Int)
資料類別最常用預定義成員函式有:
函式 | 說明 |
---|---|
toString() | 列印類別實例及其屬性的可讀字串。 |
equals() 或 == | 比較類別的實例。 |
copy() | 透過複製另一個類別實例來建立一個新實例,可能帶有一些不同的屬性。 |
請參閱以下章節以了解如何使用每個函式範例:
列印為字串
要列印類別實例的可讀字串,您可以明確呼叫 toString()
函式,或使用自動為您呼叫 toString()
的列印函式 (println()
和 print()
):
data class User(val name: String, val id: Int)
fun main() {
val user = User("Alex", 1)
// 自動使用 toString() 函式,使輸出易於閱讀
println(user)
// User(name=Alex, id=1)
}
這在除錯或建立日誌時特別有用。
比較實例
要比較資料類別實例,請使用相等運算子 ==
:
data class User(val name: String, val id: Int)
fun main() {
val user = User("Alex", 1)
val secondUser = User("Alex", 1)
val thirdUser = User("Max", 2)
// 比較 user 與 secondUser
println("user == secondUser: ${user == secondUser}")
// user == secondUser: true
// 比較 user 與 thirdUser
println("user == thirdUser: ${user == thirdUser}")
// user == thirdUser: false
}
複製實例
要建立資料類別實例的精確副本,請在該實例上呼叫 copy()
函式。
要建立資料類別實例的副本並更改某些屬性,請在該實例上呼叫 copy()
函式並將屬性的替換值作為函式參數新增。
例如:
data class User(val name: String, val id: Int)
fun main() {
val user = User("Alex", 1)
// 建立 user 的精確副本
println(user.copy())
// User(name=Alex, id=1)
// 建立 name 為 "Max" 的 user 副本
println(user.copy("Max"))
// User(name=Max, id=1)
// 建立 id 為 3 的 user 副本
println(user.copy(id = 3))
// User(name=Alex, id=3)
}
建立實例的副本比修改原始實例更安全,因為任何依賴原始實例的程式碼都不會受到副本及其操作的影響。
有關資料類別的更多資訊,請參閱資料類別。
本次導覽的最後一章是關於 Kotlin 的空值安全。
練習
練習 1
定義一個資料類別 Employee
,包含兩個屬性:一個用於名稱,另一個用於薪資。請確保薪資屬性是可變的,否則您將不會在年底獲得加薪!main
函式示範了如何使用此資料類別。
// Write your code here
fun main() {
val emp = Employee("Mary", 20)
println(emp)
emp.salary += 10
println(emp)
}
範例解答
data class Employee(val name: String, var salary: Int)
fun main() {
val emp = Employee("Mary", 20)
println(emp)
emp.salary += 10
println(emp)
}
練習 2
宣告此程式碼編譯所需的額外資料類別。
data class Person(val name: Name, val address: Address, val ownsAPet: Boolean = true)
// Write your code here
// data class Name(...)
fun main() {
val person = Person(
Name("John", "Smith"),
Address("123 Fake Street", City("Springfield", "US")),
ownsAPet = false
)
}
範例解答
data class Person(val name: Name, val address: Address, val ownsAPet: Boolean = true)
data class Name(val first: String, val last: String)
data class Address(val street: String, val city: City)
data class City(val name: String, val countryCode: String)
fun main() {
val person = Person(
Name("John", "Smith"),
Address("123 Fake Street", City("Springfield", "US")),
ownsAPet = false
)
}
練習 3
為了測試您的程式碼,您需要一個可以建立隨機員工的產生器。定義一個 RandomEmployeeGenerator
類別,其中包含一個固定潛在名稱列表 (在類別主體內)。使用最小和最大薪資配置該類別 (在類別標頭內)。在類別主體中,定義 generateEmployee()
函式。同樣地,main
函式示範了如何使用此類別。
TIP
在此練習中,您匯入了一個套件,以便您可以使用 Random.nextInt()
函式。 有關匯入套件的更多資訊,請參閱套件與匯入。
提示 1
提示 2
Random.nextInt(from = ..., until = ...)
會在指定限制內給您一個隨機的 Int
數字。 import kotlin.random.Random
data class Employee(val name: String, var salary: Int)
// Write your code here
fun main() {
val empGen = RandomEmployeeGenerator(10, 30)
println(empGen.generateEmployee())
println(empGen.generateEmployee())
println(empGen.generateEmployee())
empGen.minSalary = 50
empGen.maxSalary = 100
println(empGen.generateEmployee())
}
範例解答
import kotlin.random.Random
data class Employee(val name: String, var salary: Int)
class RandomEmployeeGenerator(var minSalary: Int, var maxSalary: Int) {
val names = listOf("John", "Mary", "Ann", "Paul", "Jack", "Elizabeth")
fun generateEmployee() =
Employee(names.random(),
Random.nextInt(from = minSalary, until = maxSalary))
}
fun main() {
val empGen = RandomEmployeeGenerator(10, 30)
println(empGen.generateEmployee())
println(empGen.generateEmployee())
println(empGen.generateEmployee())
empGen.minSalary = 50
empGen.maxSalary = 100
println(empGen.generateEmployee())
}