ProgrammazioneSenior Kotlin Developer

Come funziona la parola chiave 'super' in Kotlin e in cosa differisce dal suo utilizzo in Java? In quali casi potrebbero sorgere difficoltà di ambiguità con l'implementazione multipla di interfacce e come risolverle?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Kotlin, la parola chiave super viene utilizzata per accedere all'implementazione di un metodo o di una proprietà della superclasse o dell'interfaccia implementata. A differenza di Java, Kotlin consente di specificare esplicitamente quale interfaccia o classe chiamare per l'implementazione del metodo, il che è particolarmente importante in caso di "conflitto" tra più interfacce con metodi identici.

Caratteristica: Se una classe implementa più interfacce, ognuna delle quali definisce un metodo con la stessa firma e dispone di un'implementazione predefinita, è necessario specificare esplicitamente quale implementazione utilizzare.

Esempio:

interface A { fun foo() = println("A") } interface B { fun foo() = println("B") } class C : A, B { override fun foo() { super<A>.foo() // Chiamiamo esplicitamente A.foo super<B>.foo() // Chiamiamo esplicitamente B.foo } }

Questo non è supportato direttamente in Java (Java non consente che le interfacce abbiano campi/implementazioni dei metodi fino a Java 8, e anche in Java 8 i meccanismi sono diversi).

Domanda insidiosa

"È possibile in Kotlin accedere all'implementazione del metodo della superclasse attraverso più livelli di ereditarietà?"

  • Errore comune: si pensa di poter accedere all'implementazione tramite una classe intermedia: super<Intermediate>.foo(), ma non è così: è possibile accedere solo alla superclasse o interfaccia immediata che implementa direttamente il metodo.

Esempio:

open class Base { open fun foo() = println("Base") } open class Mid : Base() { override fun foo() { println("Mid"); super.foo() } } class Child: Mid() { override fun foo() { super.foo() // chiamerà Mid.foo() // super<Base>.foo() — errore di compilazione } }

Esempi di errori reali causati dalla mancanza di conoscenza delle sottigliezze del tema


Storia

In un grande progetto, le interfacce Logger e Auditor definivano entrambe il metodo record(). Nell'implementare una classe che ereditava entrambe le interfacce, il programmatore non ha esplicitamente sovrascritto record(), causando un errore di compilazione "La classe deve sovrascrivere il funzioni pubblica aperta record()". È stato necessario implementare manualmente il metodo e delegare esplicitamente all'interfaccia corrispondente.


Storia

Quando si tentava di chiamare il metodo implementato della superclasse attraverso più livelli intermedi (ad esempio, super<Base>.foo()), si verificava un errore di compilazione. Lo sviluppatore non conosceva le limitazioni di Kotlin e non riusciva a capire perché la chiamata diretta non fosse possibile.


Storia

Dopo l'aggiornamento dell'API, una delle interfacce ha aggiunto un'implementazione di una funzione predefinita, identica a un'altra interfaccia. Il vecchio codice non compilava più a causa di conflitti di implementazione — è stato necessario risolvere esplicitamente il conflitto, implementando il metodo da soli e scegliendo quali implementazioni delle super interfacce chiamare al suo interno.