English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Interfaces (Interface) en Kotlin

在本文中,您将借助示例学习有关接口以及如何在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 (opcional)
    }
}
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("Llamar hello(): ")
    obj.hello()
    print("Llamar e imprimir foo(): ")
    println(obj.foo())
}

Al ejecutar el programa, la salida es:

test = 25
Llamar hello(): ¡Hola, amigo!
Llamar e imprimir foo(): Lol

Como se mencionó anteriormente, las interfaces también pueden tener propiedades que proporcionan una implementación del acceso. Por ejemplo,

interface MyInterface {
    //Propiedades con implementación
    val prop: Int
        get() = 23
}
class InterfaceImp: MyInterface {
    //Cuerpo de la clase
}
fun main(args: Array<String>) {
    val obj = InterfaceImp()
    println(obj.prop)
}

Al ejecutar el programa, la salida es:

23

Aquí, prop no es abstracta, pero es válida en la interfaz porque proporciona una implementación del acceso.

Pero no puede ejecutar en el interior de una interfaz algo como val prop: Int = 23 operaciones.

Implementar dos o más interfaces en una clase

Kotlin no permite la verdadera herencia múltiple. Sin embargo, se pueden implementar dos o más interfaces en una clase. Por ejemplo,

interface A {
    fun callMe() {
        println("De la interfaz A")
    }
}
interface B {
    fun callMeToo() {
        println("De la interfaz B")
    }
}
//Implementar las interfaces A y B
class Child: A, B
fun main(args: Array<String>) {
    val obj = Child()
    obj.callMe()
    obj.callMeToo()
}

Al ejecutar el programa, la salida es:

De la interfaz A
De la interfaz B

Solución a conflictos de sobrescripción (multiples interfaces)

Supongamos que dos interfaces (A y B) tienen métodos no abstractos con el mismo nombre (supongamos que el método callMe()). Implementa ambas interfaces en una clase (supongamos que C). Ahora, si se llama al método callMe() utilizando un objeto de la clase C, el compilador lanzará un error. Por ejemplo

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

Este es el error lanzado:

Error: (14, 1Error: () Kotlin: La clase 'C' debe anular la función pública abierta fun callMe(): Unit definida en A porque hereda múltiples métodos de interfaz de la misma

Para resolver este problema, necesita proporcionar su propia implementación. Aquí está cómo hacerlo:

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

Ahora, cuando ejecute el programa, la salida será:

Interfaz  A
Interfaz  B

Aquí, se proporciona una implementación explícita del método callMe() en la clase C.

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

La instrucción super<A>.callMe() llama al método callMe() de la clase A. Del mismo modo, super<B>.callMe() llama al método callMe() de la clase B.