在本文中,您將在示例的幫助下了解Kotlin中的構(gòu)造函數(shù)(主要構(gòu)造函數(shù)和次構(gòu)造函數(shù))以及初始化程序塊。
構(gòu)造函數(shù)是初始化類屬性的簡潔方法。
它是一個特殊的成員函數(shù),在實(shí)例化(創(chuàng)建)對象時調(diào)用。但是,它們在Kotlin中的工作方式略有不同。
在Kotlin中,有兩個構(gòu)造函數(shù):
主構(gòu)造函數(shù) - 初始化類的簡潔方法
次構(gòu)造函數(shù) - 允許您放置其他初始化邏輯
主構(gòu)造函數(shù)是類標(biāo)頭的一部分。這是一個實(shí)例:
class Person(val firstName: String, var age: Int) { // class body }
用括號括起來的代碼塊是主要的構(gòu)造函數(shù):(val firstName: String, var age: Int)。
構(gòu)造函數(shù)聲明了兩個屬性:firstName(只讀屬性,因?yàn)樗鞘褂藐P(guān)鍵字val聲明的)和age(讀寫屬性,因?yàn)樗怯藐P(guān)鍵字var聲明的)。
fun main(args: Array<String>) { val person1 = Person("Joe", 25) println("First Name = ${person1.firstName}") println("Age = ${person1.age}") } class Person(val firstName: String, var age: Int) { }
運(yùn)行該程序時,輸出為:
First Name = Joe Age = 25
當(dāng)創(chuàng)建 Person 類的對象時,將傳遞值 Joe 和 25,就好像Person是一個函數(shù)一樣。
這將 person1 對象的 firstName 和 age 屬性分別初始化為 "Joe" 和 25。
還有其他使用主要構(gòu)造函數(shù)的方法。
主構(gòu)造函數(shù)的語法受約束,不能包含任何代碼。
為了放置初始化代碼(不僅是初始化屬性的代碼),使用了初始化程序塊。它以 init 關(guān)鍵字為前綴 。讓我們用初始化語句塊修改以上示例:
fun main(args: Array<String>) { val person1 = Person("joe", 25) } class Person(fName: String, personAge: Int) { val firstName: String var age: Int //初始化塊 init { firstName = fName.capitalize() age = personAge println("First Name = $firstName") println("Age = $age") } }
運(yùn)行該程序時,輸出為:
First Name = Joe Age = 25
這里,在創(chuàng)建 person1對象時,圓括號內(nèi)的參數(shù) fName 和 personAge 分別接受值 "Joe" 和 25。但是,使用 fName 和 personAge 時不使用 var 或 val,而且它們不是 Person 類的屬性。
Person類聲明了兩個屬性 firstName 和 age。
當(dāng)person1對象被創(chuàng)建,初始化塊內(nèi)部代碼被執(zhí)行。初始化程序塊不僅初始化其屬性,還打印輸出它們。
這是執(zhí)行相同任務(wù)的另一種方法:
fun main(args: Array<String>) { val person1 = Person("joe", 25) } class Person(fName: String, personAge: Int) { val firstName = fName.capitalize() var age = personAge //初始化塊 init { println("First Name = $firstName") println("Age = $age") } }
為了區(qū)分構(gòu)造函數(shù)參數(shù)和屬性,使用了不同的名稱(fName和FirstName,以及Personage和age)。 對于構(gòu)造函數(shù)參數(shù),更常見的是使用_firstName和_age,而不是完全不同的名稱。 例如:
class Person(_firstName: String, _age: Int) { val firstName = _firstName.capitalize() var age = _age // 初始化塊 init { ... .. ... } }
您可以為構(gòu)造函數(shù)參數(shù)提供默認(rèn)值(類似于為函數(shù)提供默認(rèn)參數(shù))。例如:
fun main(args: Array<String>) { println("person1 被實(shí)例化") val person1 = Person("joe", 25) println("person2 被實(shí)例化") val person2 = Person("Jack") println("person3 被實(shí)例化") val person3 = Person() } class Person(_firstName: String = "UNKNOWN", _age: Int = 0) { val firstName = _firstName.capitalize() var age = _age //初始化塊 init { println("First Name = $firstName") println("Age = $age\n") } }
運(yùn)行該程序時,輸出為:
First Name = Joe Age = 25 person2 被實(shí)例化 First Name = Jack Age = 0 person3 被實(shí)例化 First Name = UNKNOWN Age = 0
在Kotlin中,一個類還可以包含一個或多個次構(gòu)造函數(shù)。它們是使用 constructor 關(guān)鍵字創(chuàng)建的。
次構(gòu)造函數(shù)在Kotlin中并不常見。 當(dāng)您需要擴(kuò)展提供以不同方式初始化類的多個構(gòu)造函數(shù)的類時,次要構(gòu)造函數(shù)的最常見用法就出現(xiàn)了。在學(xué)習(xí)之前,請確認(rèn)已經(jīng)了解Kotlin繼承。
您可以在Kotlin中創(chuàng)建次構(gòu)造函數(shù)的方法如下:
class Log { constructor(data: String) { // 一些代碼 } constructor(data: String, numberOfData: Int) { // 一些代碼 } }
在這里,Log 類具有兩個次構(gòu)造函數(shù),但沒有主要構(gòu)造函數(shù)。
您可以將類擴(kuò)展為:
class Log { constructor(data: String) { // 代碼 } constructor(data: String, numberOfData: Int) { // 代碼 } } class AuthLog: Log { constructor(data: String): super(data) { // 代碼 } constructor(data: String, numberOfData: Int): super(data, numberOfData) { // 代碼 } }
在此,派生類 AuthLog 的構(gòu)造函數(shù)調(diào)用基類 Log 的相應(yīng)構(gòu)造函數(shù)。為此,使用 super()。
在Kotlin中,您還可以使用 this() 來從同一類的另一個構(gòu)造函數(shù)(如Java中)調(diào)用構(gòu)造函數(shù)。
class AuthLog: Log { constructor(data: String): this(data, 10) { // 代碼 } constructor(data: String, numberOfData: Int): super(data, numberOfData) { // 代碼 } }
fun main(args: Array<String>) { val p1 = AuthLog("Bad Password") } open class Log { var data: String = "" var numberOfData = 0 constructor(_data: String) { } constructor(_data: String, _numberOfData: Int) { data = _data numberOfData = _numberOfData println("$data: $numberOfData times") } } class AuthLog: Log { constructor(_data: String): this("From AuthLog -> " + _data, 10) { } constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) { } }
運(yùn)行該程序時,輸出為:
From AuthLog -> Bad Password: 10 times
注意:如果類沒有主構(gòu)造函數(shù),則次構(gòu)造函數(shù)必須將基類或委托初始化為另一個構(gòu)造函數(shù)(如上例所示)。