接口
Kotlin 的接口可以既包含抽象方法的聲明也包含實(shí)現(xiàn)粥庄。與抽象類不同的是取董,接口無(wú)法保存狀態(tài)管呵。它可以有屬性但必須聲明為抽象或提供訪問(wèn)器實(shí)現(xiàn)涧衙。
使用關(guān)鍵字 interface 來(lái)定義接口
interface MyInterface {
fun bar()
fun foo() {
// 可選的方法體
}
}
實(shí)現(xiàn)接口
一個(gè)類或者對(duì)象可以實(shí)現(xiàn)一個(gè)或多個(gè)接口。
class Child : MyInterface {
override fun bar() {
// 方法體
}
}
接口中的屬性
你可以在接口中定義屬性斋攀。在接口中聲明的屬性要么是抽象的已卷,要么提供訪問(wèn)器的實(shí)現(xiàn)。在接口中聲明的屬性不能有幕后字段(backing field)淳蔼,因此接口中聲明的訪問(wèn)器不能引用它們侧蘸。
interface MyInterface {
val prop: Int // 抽象的
val propertyWithImplementation: String
get() = "foo"
fun foo() {
print(prop)
}
}
class Child : MyInterface {
override val prop: Int = 29
}
接口繼承
一個(gè)接口可以從其他接口派生,從而既提供基類型成員的實(shí)現(xiàn)也聲明新的函數(shù)與屬性肖方。很自然地闺魏,實(shí)現(xiàn)這樣接口的類只需定義所缺少的實(shí)現(xiàn):
interface Named {
val name: String
}
interface Person : Named {
val firstName: String
val lastName: String
override val name: String get() = "$firstName $lastName"
}
data class Employee(
// 不必實(shí)現(xiàn)“name”
override val firstName: String,
override val lastName: String,
val position: Position
) : Person
解決覆蓋沖突
實(shí)現(xiàn)多個(gè)接口時(shí),可能會(huì)遇到同一方法繼承多個(gè)實(shí)現(xiàn)的問(wèn)題俯画。例如
interface A {
fun foo() { print("A") }
fun bar()
}
interface B {
fun foo() { print("B") }
fun bar() { print("bar") }
}
class C : A {
override fun bar() { print("bar") }
}
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super<B>.bar()
}
}
上例中析桥,接口 A 和 B 都定義了方法 foo() 和 bar()。 兩者都實(shí)現(xiàn)了 foo(), 但是只有 B 實(shí)現(xiàn)了 bar() (bar() 在 A 中沒(méi)有標(biāo)記為抽象艰垂, 因?yàn)闆](méi)有方法體時(shí)默認(rèn)為抽象)泡仗。因?yàn)?C 是一個(gè)實(shí)現(xiàn)了 A 的具體類,所以必須要重寫(xiě) bar() 并實(shí)現(xiàn)這個(gè)抽象方法猜憎。
然而娩怎,如果我們從 A 和 B 派生 D,我們需要實(shí)現(xiàn)我們從多個(gè)接口繼承的所有方法胰柑,并指明 D 應(yīng)該如何實(shí)現(xiàn)它們截亦。這一規(guī)則既適用于繼承單個(gè)實(shí)現(xiàn)(bar())的方法也適用于繼承多個(gè)實(shí)現(xiàn)(foo())的方法爬泥。