Sobes.tech
Junior

Come vengono implementate le interfacce in Kotlin?

sobes.tech AI

Risposta dell'AI

Le interfacce in Kotlin vengono implementate utilizzando la parola chiave implements ( implicito in Kotlin, indicato semplicemente con due punti) o by per la delega.

Principali metodi di implementazione:

  1. Implementazione diretta: L'oggetto o la classe implementa direttamente tutti i membri dell'interfaccia.
    interface MyInterface {
        fun doSomething()
        val myProperty: String
    }
    
    class MyClass : MyInterface {
        override fun doSomething() {
            println("Fare qualcosa in MyClass")
        }
    
        override val myProperty: String = "Ciao"
    }
    
    Quando si eredita da una classe e si implementano interfacce contemporaneamente, la classe viene indicata per prima.
    open class BaseClass
    
    class AnotherClass : BaseClass(), MyInterface {
        override fun doSomething() {
            println("Fare qualcosa in AnotherClass")
        }
    
        override val myProperty: String = "Mondo"
    }
    
  2. Delega di implementazione: L'implementazione dell'interfaccia viene delegata a un altro oggetto. Si usa la parola chiave by. Questo è utile per la composizione e per evitare problemi di ereditarietà multipla.
    interface DelegatedInterface {
        fun performAction()
    }
    
    class DelegatedObject : DelegatedInterface {
        override fun performAction() {
            println("Azione eseguita da DelegatedObject")
        }
    }
    
    class ImplementingClass(di: DelegatedInterface) : DelegatedInterface by di {
        // ImplementingClass delega l'implementazione del metodo performAction() all'oggetto di
    }
    
    In questo caso, ImplementingClass non implementa performAction da solo, invece, la chiamata a performingClass.performAction() viene reindirizzata a di.performAction().

Quando si implementano più interfacce con membri con lo stesso nome, è necessario risolvere i conflitti, sovrascrivendo esplicitamente il membro e specificando da quale interfaccia si prende l'implementazione, usando la sintassi <Interfaccia>.<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() // Chiamata all'implementazione di foo di InterfaceA
        super<InterfaceB>.foo() // Chiamata all'implementazione di foo di InterfaceB
    }

    override fun bar() {
        super<InterfaceB>.bar() // Usa l'implementazione di bar di InterfaceB
    }
}