一、接口声明
Kotlin中的接口可以既包含抽象方法的声明也包含实现,与抽象类不同之处在于不能保存状态。接口内可以定义属性,但这些属性必须是抽象的或提供了访问器的实现(getter)
1
2
3
4
5
6
7
8
9
interface MyInterface {
var age:Int // abstract
val name: String
get() = "lee"
fun bar()
fun foo() {
// 可选的方法体
}
}
二、接口实现
与java相同一个类或对象可以实现多个接口
1
2
3
4
5
class Child : MyInterface {
override fun bar() {
// body
}
}
三、接口中的属性
接口中属性必须是抽象的或着提供了getter的实现,接口中属性没有 backing fields,不能够在接口中的属性直接引用。
1
2
3
4
5
6
7
8
9
10
11
12
interface MyInterface {
var age:Int // abstract
val name: String
get() = "lee"
fun foo() {
// 可选的方法体
}
}
class Child : MyInterface {
override val age: 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(
// implementing 'name' is not required
override val firstName: String,
override val lastName: String,
val position: Position
) : Person
五、处理覆盖冲突
与继承的规则相同,存在同名方法是,使用super<Base>
来调用具体方法
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()
}
}
六、函数式(SAM)接口 - Single Abstract Method
1. 函数式接口声明
函数式接口可以有多个非抽象成员,但只能有一个抽象成员,声明时使用fun
修饰
1
2
3
fun interface KRunnable {
fun invoke()
}
2. SAM转换
使用SAM转换,通过lambda表达式可以让代码更简单易读,而不是手动创建函数实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
// Creating an instance of a class
val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}
//SAM conversions
val isEven = IntPredicate { it % 2 == 0 }
fun main() {
println("Is 7 even? - ${isEven.accept(7)}")
}
3. 类型别名
上面的接口我们可以通过类型别名直接定义,达到同样的效果,使用typealias
1
2
3
4
5
6
7
typealias IntPredicate = (i: Int) -> Boolean
val isEven: IntPredicate = { it % 2 == 0 }
fun main() {
println("Is 7 even? - ${isEven(7)}")
}
需要注意类型别名只能有一个成员,函数式接口可以有多个非抽象成员,而且可以实现和扩展其他接口