一:數(shù)據(jù)類
1.1:使用
我們經(jīng)常創(chuàng)建一些數(shù)據(jù)類來保存一個對象的屬性和狀態(tài),在這些類中一些標(biāo)準(zhǔn)的get set函數(shù)都是機械推導(dǎo)出來的,在kotlin中這些類被標(biāo)記為數(shù)據(jù)類,使用關(guān)鍵字data聲明
data class User(val name:String, var age: Int)
編譯器自動從數(shù)據(jù)類主構(gòu)造函數(shù)中的屬性推導(dǎo)出一下成員
- equals/hashcode對
- toString格式是“User(name=tian,age=12)"
- componentN():函數(shù)按聲明順序?qū)?yīng)所有屬性
- copy能力
數(shù)據(jù)類中的成員生成遵循成員繼承的規(guī)則,
- 如果數(shù)據(jù)類中有顯示的實現(xiàn)toString equals等函數(shù),或者在超類中這些函數(shù)有final實現(xiàn),則不會生產(chǎn)這些函數(shù),而是使用現(xiàn)有函數(shù)
- 不允許對componentN以及copy函數(shù)提供顯示實現(xiàn)
- 如果數(shù)據(jù)類需要一個無參構(gòu)造函數(shù),則主構(gòu)造函數(shù)的所有屬性必須有默認(rèn)值
data class User(val name: String = "", val age: Int = 1) //這里就會有無參構(gòu)造函數(shù)
1.2:在類體中聲明屬性
注意:數(shù)據(jù)類中自動生產(chǎn)的函數(shù)只會用到主構(gòu)造函數(shù)中的參數(shù),如果有在類體中聲明的屬性,則不會用到
data class User(var name: String) {
var age: Int = 0 // 這個屬性不會在自動生成的函數(shù)中出現(xiàn)
}
1.3:copy函數(shù)
很多時候我們需要改變數(shù)據(jù)類對象的一個屬性,而保持其他的不變,我們就可以使用copy函數(shù)
var user = User("tian", 12)
var olderUser = user.copy(age = 21)
二:密封類
密封類表示有限的類繼承結(jié)構(gòu),當(dāng)一個值為有限集中的類型,而不能有任何其他類型時??梢岳斫馑鼮槊杜e類的擴展。密封類使用sealed修飾,默認(rèn)是open的類,
注意:密封類和它的子類都必須聲明在相同的文件中
sealed class Person
object Man : Person()
object Woman : Person()
fun test(person: Person) {
when(person) {
is Man -> println("man")
is Woman -> println("woman")
}
}
可以看到這里的when沒有了else,這是密封類最常用的時候,密封類因為有有限的類繼承結(jié)構(gòu),所以在使用when時我們可以全部覆蓋密封類的子類,但我們臨時添加一個子類時,在編譯時when因為沒有全部覆蓋密封類的子類,就會報錯,這樣我們就能在編譯期間查詢到錯誤,更容易使程序健壯
特點:密封類默認(rèn)是抽象的無法實例化,構(gòu)造函數(shù)默認(rèn)是private的,
三:嵌套類
類也可以嵌套在其他類中, 無法訪問外部類
class Outer{
private val bar:Int = 1
class Nested{
fun foo() = 2
}
}
val demo = Outer.Nested().foo()
四:內(nèi)部類
內(nèi)部類與嵌套類不同為它可以訪問外部類,內(nèi)部類使用inner標(biāo)記,內(nèi)部類會有一個對外部類的對象引用。
class Outer{
private val bar:Int = 1
inner class Nested{
fun foo() = bar
}
}
val demo = Outer.Nested().foo() //demo = 1
五:枚舉類
:5.1:基本使用
枚舉類最基本的用法是實現(xiàn)類型安全的枚舉,每個枚舉常量都是一個對象,多個常量用逗號分割
enum class Direction{
NORTH, SOUTH, WEST, EAST
}
enum class TIme(var number: Int){ //帶參數(shù)的枚舉類
HOUR(1),
YEAR(2),
SECOND(3)
}
5.2:枚舉類中的自定義成員
枚舉類中也可以有自己的匿名類,相應(yīng)的方法,以及覆蓋基類的方法,
注意:枚舉類內(nèi)定義任何成員需要跟枚舉成員對象用分號隔開
enum class Time(val age: Int) {
HOUR(1) {
override fun sign() = HOUR
},
YEAR(2){
override fun sign() = YEAR
},
SECOND(3){
override fun sign() = SECOND
}; //在這里用分號把枚舉類成員對象和枚舉類內(nèi)定義的成員分開
abstract fun sign(): Time
}
5.3:枚舉類的接口實現(xiàn)
枚舉類可以實現(xiàn)接口但不能繼承類,可以為所有枚舉類成員對象提供統(tǒng)一的實現(xiàn),也可以在相應(yīng)的匿名類中單獨實現(xiàn),
interface ITime {
fun test()
}
enum class Time(val age: Int) : ITime {
HOUR(1) {
override fun sign() = HOUR
override fun test() { //這里是為所有枚舉類成員對象單獨實現(xiàn)接口成員
super.test() //這里的super代表的就是Time枚舉類,這個調(diào)用的是Time中的test函數(shù)
println("Hour test")
}
},
YEAR(2){
override fun sign() = YEAR
},
SECOND(3){
override fun sign() = SECOND
};
abstract fun sign(): Time
override fun test() { //這里是為所有枚舉類成員對象統(tǒng)一實現(xiàn)接口成員
println("Time test")
}
}
5.4:使用枚舉類
枚舉類可以使用valueOf和values函數(shù)來進行訪問
val time = Time.valueOf("YEAR") //根據(jù)參數(shù)YEAR,從Time枚舉類中獲取YEAR,傳入的字符串就是枚舉類對象成員的名字
val times = Time.values() //這里會獲取Time枚舉類中所有的對象成員,返回的是Array類型
for (t in times) {
println(t)
}
使用enumValueOf和enumValues函數(shù)這兩個函數(shù)與上面兩個函數(shù)返回的結(jié)果是一樣的
enumValueOf<Time>("YEAR") //使用泛型指定要操作的枚舉類,返回值為TIme
enumValues<Time>() //返回為TIme的Array類型