Sobes.tech
Junior

Como é que a implementação de interfaces é feita em Kotlin?

sobes.tech IA

Resposta da IA

As interfaces em Kotlin são implementadas usando a palavra-chave implements (implícito em Kotlin, simplesmente indicado por dois pontos) ou by para delegação.

Principais formas de implementação:

  1. Implementação direta: O objeto ou classe implementa todos os membros da interface diretamente.
    interface MyInterface {
        fun doSomething()
        val myProperty: String
    }
    
    class MyClass : MyInterface {
        override fun doSomething() {
            println("Fazendo algo em MyClass")
        }
    
        override val myProperty: String = "Olá"
    }
    
    Quando se herda de uma classe e se implementam interfaces ao mesmo tempo, a classe é indicada primeiro.
    open class BaseClass
    
    class AnotherClass : BaseClass(), MyInterface {
        override fun doSomething() {
            println("Fazendo algo em AnotherClass")
        }
    
        override val myProperty: String = "Mundo"
    }
    
  2. Delegação de implementação: A implementação da interface é delegada a outro objeto. Usa-se a palavra-chave by. Isto é útil para composição e para evitar problemas com herança múltipla de implementação.
    interface DelegatedInterface {
        fun performAction()
    }
    
    class DelegatedObject : DelegatedInterface {
        override fun performAction() {
            println("Ação realizada por DelegatedObject")
        }
    }
    
    class ImplementingClass(di: DelegatedInterface) : DelegatedInterface by di {
        // ImplementingClass delega a implementação do método performAction() ao objeto di
    }
    
    Neste caso, ImplementingClass não implementa performAction por si só, ao invés disso, a chamada a performingClass.performAction() é redirecionada para di.performAction().

Ao implementar múltiplas interfaces com membros com o mesmo nome, é necessário resolver conflitos, sobrescrevendo explicitamente o membro e indicando de qual interface a implementação é obtida, usando a sintaxe <Interface>.<membro>.

interface InterfaceA {
    fun foo() { println("InterfaceA") }
    fun bar()
}

interface InterfaceB {
    fun foo() { println("InterfaceB") }
    fun bar() { println("InterfaceB bar") }
}

class ResolvingConflict : InterfaceA, InterfaceB {
    override fun foo() {
        super<InterfaceA>.foo() // Chama a implementação de foo de InterfaceA
        super<InterfaceB>.foo() // Chama a implementação de foo de InterfaceB
    }

    override fun bar() {
        super<InterfaceB>.bar() // Usa a implementação de bar de InterfaceB
    }
}