5.8.4 接口
原文链接: https://kotlinlang.org/docs/interfaces.html
5.8.4 接口
Kotlin 中的接口既可以包含抽象方法的声明,也可以包含方法的实现。它们与抽象类的不同之处在于:接口不能保存状态。接口可以有属性,但这些属性必须是抽象的,或者提供访问器的实现。
接口使用关键字 interface 定义:
1
2
3
4
5
6
| interface MyInterface {
fun bar()
fun foo() {
// 可选的函数体
}
}
|
实现接口
一个类或对象可以实现一个或多个接口:
1
2
3
4
5
| class Child : MyInterface {
override fun bar() {
// 函数体
}
}
|
接口中的属性
你可以在接口中声明属性。接口中声明的属性既可以是抽象属性,也可以为访问器提供实现。接口中声明的属性不能有幕后字段,因此接口中声明的访问器不能引用它们:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| interface MyInterface {
val prop: Int // 抽象
val propertyWithImplementation: String
get() = "foo"
fun foo() {
print(prop)
}
}
class Child : MyInterface {
override val prop: Int = 29
}
|
接口继承
接口可以派生自其他接口,也就是说它既可以为其成员提供实现,也可以声明新的函数和属性。很自然,实现这类接口的类只需要定义缺失的实现即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| interface Named {
val name: String
}
interface Person : Named {
val firstName: String
val lastName: String
override val name: String get() = "$firstName $lastName"
}
data class Employee(
// 不需要实现 'name'
override val firstName: String,
override val lastName: String,
val position: Position
) : Person
|
解析重写冲突
当你在超类型列表中声明许多类型时,可能会继承同一个方法的多个实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| 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()。它们都实现了 foo(),但只有 B 实现了
bar()(bar() 在 A 中未标记为抽象,因为函数没有函数体时这正是接口的默认情况)。现在,如果你从 A 派生出一个具体类 C,就必须重写 bar() 并提供实现。
然而,如果你从 A 和 B 派生出 D,则需要实现从多个接口继承来的所有方法,并指明 D 究竟应该如何实现它们。这条规则既适用于只继承了单个实现的方法(bar()),也适用于继承了多个实现的方法(foo())。
接口函数的 JVM 默认方法生成
在 JVM 上,接口中声明的函数会被编译为默认方法。你可以用 -jvm-default 编译器选项控制这一行为,它有以下取值:
enable(默认):在接口中生成默认实现,并在子类和 DefaultImpls 类中包含桥接函数。使用此模式可以保持与旧版 Kotlin 的二进制兼容性。no-compatibility:只在接口中生成默认实现。此模式会跳过兼容性桥接和 DefaultImpls 类,适合新的 Kotlin 代码。disable:跳过默认方法,只生成兼容性桥接和 DefaultImpls 类。
要配置 -jvm-default 编译器选项,请在 Gradle Kotlin DSL 中设置 jvmDefault 属性:
1
2
3
4
5
| kotlin {
compilerOptions {
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
}
}
|