Kotlin 接口

Kotlin 接口与 Java 8 中的接口类似。它们可以包含抽象方法的定义以及非抽象方法的实现。但是,它们不能包含任何状态。

也就是说,接口可以有属性,但必须是抽象的,或者提供访问器实现。


推荐阅读: Kotlin 抽象类

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


如何定义接口?

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

interface MyInterface {

    var test: String   // abstract property

    fun foo()          // abstract method
    fun hello() = "Hello there" // method with default implementation
}

这里,

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

如何实现接口?

类或对象可以这样实现接口:

interface MyInterface {

    val test: Int   // abstract property

    fun foo() : String   // abstract method (returns String)
    fun hello() {   // method with default implementation
        // body (optional)
    }
}

class InterfaceImp : MyInterface {

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

    // other code
}

这里,类 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("Calling hello(): ")

    obj.hello()

    print("Calling and printing foo(): ")
    println(obj.foo())
}

运行程序后,输出将是

test = 25
Calling hello(): Hello there, pal!
Calling and printing foo(): Lol

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

interface MyInterface {

    // property with implementation
    val prop: Int
        get() = 23
}

class InterfaceImp : MyInterface {
    // class body
}

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()
}

运行程序后,输出将是

From interface A
From interface B

解决覆盖冲突(多接口)

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

interface A {

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

interface B  {
    fun callMe() {
        println("From interface 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("From interface A")
    }
}

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

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

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

    obj.callMe()
}

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

From interface A
From interface B

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

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

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

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战