ProgrammazioneSviluppatore Kotlin

Quali sono le differenze tra classi normali, classi astratte e interfacce in Kotlin, quando e quale strumento utilizzare?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della domanda:

Kotlin ha unito il meglio di Java e dell'eredità funzionale della JVM. Le classi normali vengono dichiarate come strutture standard, le classi astratte consentono di creare modelli non completamente definiti con implementazioni predefinite, mentre le interfacce supportano l'ereditarietà multipla del comportamento senza stato.

Problema:

La scelta corretta tra classe, classe astratta e interfaccia definisce l'architettura dell'applicazione, la granularità del codice e la sua estendibilità. Un'ereditarietà errata porta a complessità nei test e nei futuri cambiamenti.

Soluzione:

In Kotlin:

  • Classe normale: definisce struttura e comportamento. Può essere ereditata se dichiarata open.
  • Classe astratta: non può essere creata direttamente. Può contenere implementazioni e/o metodi astratti (senza corpo).
  • Interfaccia: implicitamente aperta, implementa contratti, consente l'implementazione di metodi, ma non memorizza stato (solo proprietà senza backing field).

Esempio di codice:

interface Drawable { fun draw() } abstract class Shape(var color: String) : Drawable { abstract fun calcArea(): Double override fun draw() = println("Forma disegnata") } class Circle(color: String, val radius: Double) : Shape(color) { override fun calcArea() = Math.PI * radius * radius }

Caratteristiche chiave:

  • Le interfacce consentono implementazione multipla, le classi astratte solo una
  • Le interfacce non possono memorizzare stato, le classi astratte possono
  • Una classe astratta può implementare parte delle interfacce e contenere la propria logica comune

Domande trabocchetto.

Le interfacce possono contenere proprietà con backing field?

No, possono definire solo la firma della proprietà, ma non memorizzare dati — proprietà senza backing field.

È possibile ereditare da più classi?

No, Kotlin supporta solo l'ereditarietà singola delle classi, ma l'implementazione multipla delle interfacce.

È possibile dichiarare un costruttore in un'interfaccia?

No, l'interfaccia non supporta i costruttori perché non memorizza stato — solo contratti di comportamento.

Errori tipici e anti-pattern

  • Utilizzo di una classe astratta invece di un'interfaccia senza necessità
  • Memorizzazione di stato in un'interfaccia (impossibile, ma si sbaglia nella progettazione)
  • Progettazione di gerarchie di classi che complicano l'estensione

Esempio dalla vita reale

Caso negativo

Nell'applicazione tutte le funzioni comuni sono state spostate in una classe astratta, anche se non c'era logica interna o stato, ma la necessità era solo un contratto comune.

Vantaggi:

  • Unico punto di modifica per la logica comune

Svantaggi:

  • Problemi con l'ereditarietà multipla, difficile integrazione con altre strutture

Caso positivo

Solo i contratti necessari sono stati spostati in interfacce, le classi astratte sono state limitate a proprietà e metodi comuni che richiedono implementazione.

Vantaggi:

  • Estensibilità flessibile, modularità, contratti chiari

Svantaggi:

  • Richiede progettazione in fase iniziale