跳到主要内容

Kotlin 接口

提示
  1. 定义和实现接口:在 Kotlin 中,使用 interface 关键字来定义接口。接口可以包含抽象方法和带有实现的非抽象方法。要实现接口,类必须重写接口中的所有抽象成员。
  2. 接口中的属性和方法:接口可以有属性,但它们必须是抽象的或提供访问器的实现。接口中的方法可以是抽象的,也可以有默认实现,类似于 Java 8 接口。
  3. 解决接口重写冲突:当一个类实现多个接口,且这些接口中有同名的非抽象方法时,类必须提供这些方法的明确实现来解决重写冲突。

Kotlin 中的接口类似于 Java 8 中的接口。它们既可以包含抽象方法的定义,也可以包含非抽象方法的实现。然而,它们不能包含任何状态。

这意味着,接口可能有属性,但它必须是抽象的或必须提供访问器的实现。

推荐阅读:Kotlin 抽象类

Kotlin 中的抽象类与接口类似,但有一个重要区别。抽象类的属性不一定要是抽象的或提供访问器的实现。

如何定义接口?

使用关键字 interface 来在 Kotlin 中定义接口。例如,

interface MyInterface {

var test: String // 抽象属性

fun foo() // 抽象方法
fun hello() = "Hello there" // 带有默认实现的方法
}

这里,

  • 创建了一个接口 MyInterface
  • 该接口有一个抽象属性 test 和一个抽象方法 foo()
  • 该接口还有一个非抽象方法 hello()

如何实现接口?

这是一个类或对象如何实现接口的示例:

interface MyInterface {

val test: Int // 抽象属性

fun foo() : String // 抽象方法(返回 String)
fun hello() { // 带有默认实现的方法
// 主体(可选)
}
}

class InterfaceImp : MyInterface {

override val test: Int = 25
override fun foo() = "Lol"

// 其他代码
}

这里,类 InterfaceImp 实现了 MyInterface 接口。

该类重写了接口的抽象成员(test 属性和 foo() 方法)。

示例:接口如何工作?

interface MyInterface {

val test: Int

fun foo() : String

fun hello() {
println("Hello there, pal!")
}
}

class InterfaceImp : MyInterface {

override val test: Int = 25
override fun foo() = "Lol"

}

fun main(args: Array<String>) {
val obj = InterfaceImp()

println("test = ${obj.test}")
print("调用 hello(): ")

obj.hello()

print("调用并打印 foo(): ")
println(obj.foo())
}

当你运行程序时,输出将是:

test = 25
调用 hello(): Hello there, pal!
调用并打印 foo(): Lol

如上所述,接口也可以有提供访问器实现的属性。例如,

interface MyInterface {

// 带有实现的属性
val prop: Int
get() = 23
}

class InterfaceImp : MyInterface {
// 类主体
}

fun main(args: Array<String>) {
val obj = InterfaceImp()

println(obj.prop)
}

当你运行程序时,输出将是:

23

这里,prop 不是抽象的。但在接口中有效,因为它为访问器提供了实现。

然而,你不能在接口中做像 val prop: Int = 23 这样的事情。

在一个类中实现两个或更多接口

Kotlin 不允许真正的多重继承。然而,可以在单个类中实现两个或更多接口。例如,

interface A {

fun callMe() {
println("From interface A")
}
}

interface B {
fun callMeToo() {
println("From interface B")
}
}

// implements two interfaces A and B
class Child: A, B

fun main(args: Array<String>) {
val obj = Child()

obj.callMe()
obj.callMeToo()
}

当你运行程序时,输出将是:

来自接口 A
来自接口 B

解决重写冲突(多接口)

假设,两个接口(AB)都有同名的非抽象方法(比如说 callMe() 方法)。你在一个类中(比如说 C)实现了这两个接口。现在,如果你使用类 C 的对象调用 callMe() 方法,编译器将抛出错误。例如,

interface A {

fun callMe() {
println("来自接口 A")
}
}

interface B {
fun callMe() {
println("来自接口 B")
}
}

class Child: A, B

fun main(args: Array<String>) {
val obj = Child()

obj.callMe()
}

这是错误信息:

错误:(14, 1) Kotlin: 类 'C' 必须重写在 A 中定义的公开开放函数 callMe(): Unit,因为它继承了多个接口方法

要解决这个问题,你需要提供自己的实现。以下是如何操作:

interface A {

fun callMe() {
println("来自接口 A")
}
}

interface B {
fun callMe() {
println("来自接口 B")
}
}

class C: A, B {
override fun callMe() {
super<A>.callMe()
super<B>.callMe()
}
}

fun main(args: Array<String>) {
val obj = C()

obj.callMe()
}

现在当你运行程序时,输出将是:

来自接口 A
来自接口 B

这里,在类 C 中提供了 callMe() 方法的明确实现。

class C: A, B {
override fun callMe() {
super<A>.callMe()
super<B>.callMe()
}
}

语句 super<A>.callMe() 调用了类 AcallMe() 方法。类似地,super<B>.callMe() 调用了类 BcallMe() 方法。