介紹
除了與Java類比的這些功能之外,Kotlin還新增了一些新的概念
- 數據類(data)
- 擴展函數
- 密封類(sealed)
- 匿名類
- 伴生對象(Companion)
數據類
通過data
關鍵字來定義數據類。通常用來定義純數據類型的結構體。定義的數據類只能有一個主構造函數定義該數據類中的變量。而在該類中,可以定義函數
data class Date(var year: Int = 10, var month: Int, var day: Int) { fun getDay(): String { return "year:$year...month:$month...day:$day" } }
擴展函數
在Java中,如果有一個數據類需要轉換成各種格式的結構,或者需要對屬性做一些處理返回,通常會通過util
或者wrappe
來對數據結構做封裝。而在Kotlin中提供了擴展函數可以來完成這一些操作。
我們可以在使用的類中,通過以下方式來定義類的擴展函數。但是該擴展函數的使用範圍僅在這個類中使用。而該函數內有this
指針,代表着調用該函數的對象,可以直接訪問這個對象的成員
fun ClassName.Function():ReturnType{ // TODO }
例如:接上述代碼,有一個類Date
代表日期,在Child
類中,代表生日,而在Product
類中代表生產日期。那麼就可以:
open class Child(name: String, age: Int = 18) : AbsPerson(name) { override var mAge = age fun childBirthDay(date: Date): String { return date.birthDay() } fun Date.birthDay(): String { return "Child BirthDay ${this.getDay()}...${this.year}" } }
而在Product
類中,可以直接通過Date.craeteDay
來調用:
class Product { fun createDay(date: Date) { date.creatDay() } fun Date.creatDay() { this.getDay() } }
通過擴展函數的方式來完成對與數據類以及其他類的隔離,保證各個類之間的隔離。同樣,Kotlin也支持擴展屬性,與函數類似定義。
密封類
密封類用來表示受限制的類繼承結構。由於enum
每一個實例都是一個常量,所以密封類被開發,密封類的子類可以有多個實例。
聲明密封類後,也可以定義多個子類,但是這些子類都需要在與密封類同一個文件中。
// 聲明SealedClass類 sealed class SealedClass // 定義數據類繼承自SealedClass data class SealedDataClass(var data: Int) : SealedClass() // 定義通用類繼承自SealedClass class SealedConstClass : SealedClass()
而它的用處最經典的是,在when
子句中判斷類型
fun choose(data: SealedClass) { when(data){ is SealedConstClass -> data.hashCode() is SealedDataClass -> data.value } }
匿名類
Java中可以通過new
關鍵字創建匿名類,而Kotlin中則通過object
關鍵字來定義匿名類。
通過函數返回的匿名對象必須是private
聲明的函數。否則無法解析。而匿名類也可以繼承類:
class Teenager { fun runFast() { var round = object { var time: Long = 0 var distance: Long = 0 } round.time = 10 round.distance = 100 var round2 = runFast2() round2.distance = 100 round2.time = 10 round2.walk() } private fun runFast2() = object : Child("Bob") { var time: Long = 0 var distance: Long = 0 } }
伴生對象(Companion)
用伴生對象聲明的對象,與類沒有什麼關係,可以使用類名直接調用,例如在實現單例的時候可以直接使用。
class Teenager private constructor() { companion object Teen { var teenager: Teenager = Teenager() } fun runFast() { Log.e("Tag", "runFast") } }
在使用的時候,可以直接訪問並且調用
Teenager.teenager.runFast()
如果不使用companion
修飾的話,則需要調用
Teenager.Teen.teenager.runFast()