4.1 接口的定義
接口使用
interface關(guān)鍵字,kotlin中的實(shí)現(xiàn)和繼承使用:冒號(hào)代替implement和extend
接口定義
//包含一個(gè)抽象方法,這個(gè)抽象方法有默認(rèn)的實(shí)現(xiàn)
interface Clickable{
fun click() = println("cat is clicked")
}
接口的實(shí)現(xiàn)
class Cat :Clickable{
//實(shí)現(xiàn)接口里的抽象方法
override fun click() {
}
}
如上,kotlin接口的抽象方法可以有一個(gè)默認(rèn)實(shí)現(xiàn),此時(shí)子類可以不用實(shí)現(xiàn)這個(gè)方法,默認(rèn)調(diào)用父類里的方法實(shí)現(xiàn)
注意:如果我們實(shí)現(xiàn)了有重名方法的兩個(gè)接口,此時(shí)必須提供自己的方法實(shí)現(xiàn)
interface Clickable{
fun click() = println("cat is clicked")
}
interface Focusable{
fun click() = println("cat is focused")
}
class Cat :Clickable,Focusable{
override fun click() {
super<Clickable>.click()
super<Focusable>.click()
}
}
使用super<Clickable>.click()調(diào)用接口的方法的實(shí)現(xiàn),在尖括號(hào)里指明調(diào)用的基類的名稱
4.2 繼承控制修飾符
Java中所有的類和方法默認(rèn)是open的,可以繼承和重寫(xiě)的。但是kotlin中默認(rèn)是final的,如果想創(chuàng)建一個(gè)子類,需要用open來(lái)修飾這個(gè)類。而且,需要給每個(gè)需要被重寫(xiě)的方法和屬性添加open修飾符
| 修飾符 | 相關(guān)成員 | 備注 |
|---|---|---|
| final | 不能被重寫(xiě) | 類中的成員默認(rèn)使用 |
| open | 可以被重寫(xiě) | 需要明確的聲明 |
| abstract | 可以被重寫(xiě) | 修飾抽象類,修飾的抽象成員不能有實(shí)現(xiàn) |
| override | 修飾重寫(xiě)的父類的方法或者參數(shù) | 如果沒(méi)有使用final修飾,這個(gè)重寫(xiě)的成員還是開(kāi)放的即open的 |
//使用open修飾符修飾的類才能被繼承
open class Dog(){
}
4.3 可見(jiàn)性修飾符
Kotlin中的可見(jiàn)性修飾符同樣可以使用:public、protected、private,默認(rèn)可見(jiàn)性為public
- Java中的默認(rèn)可見(jiàn)性是-包私有,Kotlin只是把包作為代碼的組織方式,并沒(méi)有做可見(jiàn)性的控制
- Kotlin中提供了一種新的修飾符internal,表示模塊內(nèi)部可見(jiàn),一個(gè)模塊理解為一起編譯的Kotlin文件
- Kotlin允許在頂層聲明中使用private關(guān)鍵字,包括類、函數(shù)和屬性,只在聲明他們的文件中可見(jiàn)
| 修飾符 | 類成員 | 頂層聲明 |
|---|---|---|
| public(默認(rèn)) | 所有地方可見(jiàn) | 所有地方可見(jiàn) |
| internal | 模塊中可見(jiàn) | 模塊中可見(jiàn) |
| protected | 子類中可見(jiàn) | - |
| private | 類中可見(jiàn) | 文件中可見(jiàn) |
4.4 內(nèi)部類和嵌套類
Kotlin中可以把類定義在其他類中,但是默認(rèn)是不持有外部類的引用的,叫嵌套類
想要從嵌套類中訪問(wèn)外部類的引用,需要使用inner修飾符將其定義成內(nèi)部類,如下
/**
* 1.Kotlin中類可以嵌套在其他類中,默認(rèn)是靜態(tài)內(nèi)部類
* 2.使用inner修飾的內(nèi)部類為非靜態(tài)內(nèi)部類,才可以訪問(wèn)外部類的參數(shù)和引用
* 3.inner修飾的內(nèi)部類訪問(wèn)外部類的引用時(shí),可以用this@外部類 的方式訪問(wèn)
*/
class OuterClass() {
val name: String = "haha"
inner class Inner {
fun getOutParam() = name
fun getOutClass() = this@OuterClass.name
}
}
4.5 密封類
密封類,用來(lái)表示受限的類繼承結(jié)構(gòu):當(dāng)一個(gè)值為有限集中的類型、而不能有其他類型時(shí)。
聲明一個(gè)密封類,用sealed修飾符,而且其子類要和這個(gè)密封類定義在同一個(gè)文件中
sealed class Animal
class Fish() : Animal()
class Sheep() : Animal()
fun switchAnimal(animal: Animal) =
when (animal) {
is Fish -> println("this is a fish")
is Sheep -> println("this is a sheep")
}
如上,密封類的關(guān)鍵好處在于使用when表達(dá)式時(shí),如果驗(yàn)證語(yǔ)句覆蓋了所有的情況,那么我們不需要再提供else子句了。
4.6 構(gòu)造函數(shù)和初始化塊
Kotlin中構(gòu)造函數(shù)由一個(gè)主構(gòu)造函數(shù)和多個(gè)從構(gòu)造函數(shù)組成
主構(gòu)造函數(shù): 是類頭的一部分,定義在類名后面
class Apple constructor(val size:Float,val color:Int)
當(dāng)主構(gòu)造函數(shù)沒(méi)有注解或者可見(jiàn)性修飾符修飾時(shí)constructor可以省略,由于主構(gòu)造函數(shù)不能包含任何代碼,初始化等代碼可以放在初始化塊中init{}
//省略constructor關(guān)鍵字
class Apple(val size:Float,val color:Int){
init {
//初始化代碼
}
}
從構(gòu)造函數(shù):可以聲明多個(gè)前綴為constructor的從構(gòu)造函數(shù)
自定義view通常要寫(xiě)幾個(gè)構(gòu)造函數(shù),MyButton有三個(gè)從構(gòu)造函數(shù),沒(méi)有主構(gòu)造函數(shù)
class MyButton : View {
//使用this委托給兩個(gè)參數(shù)的構(gòu)造函數(shù)
constructor(context: Context) : this(context, null)
//使用this委托給三個(gè)參數(shù)的構(gòu)造函數(shù)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
//使用super調(diào)用父類的構(gòu)造函數(shù),初始化其基類
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
}
}
如果類沒(méi)有主構(gòu)造函數(shù),那么每個(gè)從構(gòu)造函數(shù)必須使用super關(guān)鍵字初始化其基類,或者委托另一個(gè)構(gòu)造函數(shù)做到這一點(diǎn)。