Kotlin 接口(Interface)

在本文中,您将借助示例学习有关接口以及如何在Kotlin中实现接口的知识。

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   //抽象方法(返回字符串)
    fun hello() {   //具有默认实现的方法
        // body (optional)
    }
}

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("你好,伙计!")
    }
}

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(): 你好,伙计!
调用和打印 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("来自接口A")
    }
}

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

//实现两个接口A和B
class Child: A, B

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

    obj.callMe()
    obj.callMeToo()
}

运行该程序时,输出为:

来自接口A
来自接口B

解决重写冲突(多接口)

假设两个接口(A和B)具有相同名称的非抽象方法(假设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()
}

这是抛出的错误:

Error:(14, 1) Kotlin: Class 'C' must override public open fun callMe(): Unit defined in A because it inherits multiple interface methods of it

要解决此问题,您需要提供自己的实现。这是如何做:

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()调用类A的callMe()方法。类似地,super<B>.callMe()调用类B的callMe()方法。