0Pricing
Kotlin Academy · Lezione

Delega ai membri

Componga il comportamento

Delega ai membri è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.

Comporre il comportamento

Gli oggetti reali spesso devono combinare diverse funzionalità. Invece di ereditare da più sorgenti, è possibile delegare ogni funzionalità a un oggetto membro dedicato.

Due ruoli, una classe

Supponga che una classe debba sia leggere sia scrivere. Definisca due interfacce e deleghi ciascuna alla propria implementazione.

interface Reader { fun read(): String }
interface Writer { fun write(s: String): String }

class FileReader : Reader { override fun read() = "contents" }
class FileWriter : Writer { override fun write(s: String) = "wrote " + s }

class FileIO(r: Reader, w: Writer) : Reader by r, Writer by w

fun main() {
    val io = FileIO(FileReader(), FileWriter())
    println(io.read())
    println(io.write("data"))
}

Più delegati

Una classe può delegare contemporaneamente diverse interfacce, ciascuna a un membro diverso. La classe compone i relativi comportamenti senza ricorrere all'ereditarietà.

interface Logger { fun log(m: String): String }
interface Validator { fun valid(m: String): Boolean }

class ConsoleLogger : Logger { override fun log(m: String) = "LOG: " + m }
class LengthValidator : Validator { override fun valid(m: String) = m.isNotEmpty() }

class Service(l: Logger, v: Validator) : Logger by l, Validator by v

fun main() {
    val s = Service(ConsoleLogger(), LengthValidator())
    println(s.valid("hi"))
    println(s.log("started"))
}

Il delegato memorizzato come membro

Quando è necessario fare riferimento al delegato negli override, lo si conservi come proprietà del costruttore. La stessa istanza viene usata sia dall'inoltro sia dal codice personalizzato.

interface Cache { fun get(k: String): String }

class MapCache : Cache {
    override fun get(k: String) = "value-of-" + k
}

class TracingCache(private val inner: Cache) : Cache by inner {
    override fun get(k: String): String {
        println("lookup " + k)
        return inner.get(k)
    }
}

fun main() {
    println(TracingCache(MapCache()).get("id"))
}

Combinare delegazione e stato proprio

Una classe che usa la delegazione può aggiungere proprie proprietà e propri metodi accanto a quelli inoltrati, arricchendo l'oggetto composto.

interface Engine { fun start(): String }
class V8 : Engine { override fun start() = "vroom" }

class Car(e: Engine) : Engine by e {
    var doors = 4
    fun honk() = "beep"
}

fun main() {
    val c = Car(V8())
    println(c.start())
    println(c.honk())
    println(c.doors)
}

Sostituire le implementazioni

Poiché il delegato è semplicemente un membro, è possibile creare lo stesso wrapper con implementazioni sottostanti diverse, scegliendo il comportamento a runtime.

interface Notifier { fun send(msg: String): String }
class EmailNotifier : Notifier { override fun send(msg: String) = "email: " + msg }
class SmsNotifier : Notifier { override fun send(msg: String) = "sms: " + msg }

class Alerts(n: Notifier) : Notifier by n

fun main() {
    println(Alerts(EmailNotifier()).send("hi"))
    println(Alerts(SmsNotifier()).send("hi"))
}

Delegare a una proprietà

L'espressione dopo by può essere qualsiasi espressione valutata una sola volta, inclusa una chiamata al costruttore. Non deve necessariamente essere un parametro.

interface Greeter { fun greet() = "hi" }
class DefaultGreeter : Greeter

class Page : Greeter by DefaultGreeter()

fun main() {
    println(Page().greet())
}

Evitare il problema del diamante

L'ereditarietà multipla del comportamento è impossibile con le classi, ma delegare diverse interfacce a membri separati aggira in modo pulito il classico problema del diamante.

interface A { fun a() = "A" }
interface B { fun b() = "B" }
class AImpl : A
class BImpl : B

class Combined : A by AImpl(), B by BImpl()

fun main() {
    val c = Combined()
    println(c.a() + c.b())
}

Progettare per la composizione

Per comporre bene:

  • Definisca interfacce piccole e mirate
  • Fornisca implementazioni riutilizzabili
  • Deleghi ogni ruolo nella classe che compone

In questo modo le classi restano flessibili e facili da testare.

Riepilogo della delegazione a membri

Delegare a oggetti membri consente a una classe di assemblare il comportamento a partire da più componenti. È possibile combinare molte interfacce, eseguire override selettivi, sostituire le implementazioni e aggiungere il proprio stato, tutto senza ricorrere all'ereditarietà.

Prossimo argomento: un confronto diretto

Ha visto quanto sia flessibile la delegazione. Nella prossima lezione confronteremo direttamente la delegazione e l'ereditarietà, così saprà quando scegliere l'una o l'altra.

Verifica rapida

Verifichi la sua comprensione della delegazione a membri.

Riepilogo

Ha imparato la delegazione a membri:

  • Delegare diverse interfacce a oggetti separati
  • Eseguire override selettivi e aggiungere il proprio stato
  • Sostituire le implementazioni al momento della costruzione
  • Evitare le insidie dell'ereditarietà multipla

Prossimo argomento: delegazione e ereditarietà.

Domande Frequenti

La lezione «Delega ai membri» è gratuita?

Sì — il testo completo di «Delega ai membri» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.

Cosa imparerò in «Delega ai membri»?

Componga il comportamento Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Kotlin Academy?

Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Delega ai membri»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?

Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. La keyword by
  2. Delega ai membri
  3. Delega e ereditarietà
  4. Pattern pratici
← Torna a Kotlin Academy