Menu
Coddy logo textTech

Delegation

Teil des Abschnitts Object Oriented Programming der Lua-Journey von Coddy — Lektion 50 von 70.

Das Speichern eines Objekts innerhalb eines anderen Objekts ist nur der erste Schritt. Die wahre Stärke der Komposition kommt von der Delegation – wenn das äußere Objekt Methodenaufrufe an seine inneren Komponenten weiterleitet.

Stellen Sie sich vor, Sie starten ein Auto. Sie greifen nicht unter die Motorhaube und drehen den Motor manuell an. Stattdessen drehen Sie den Schlüssel um, und das Auto erledigt den Rest intern.

Im Code bedeutet dies, dass die Car-Klasse eine einfache :start()-Methode bereitstellt, die die eigentliche Arbeit an den Motor delegiert:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- Delegieren an das innere Objekt
end

Das Auto muss nicht wissen, wie der Motor läuft—es weist den Motor lediglich an, seine Arbeit zu erledigen. Dies hält die Verantwortlichkeiten getrennt. Die Klasse Engine verarbeitet die Motorlogik, während Car die Teile koordiniert:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Ausgabe:
-- Schlüssel wird gedreht...
-- Motor läuft mit 250 HP

Delegation schafft eine saubere Schnittstelle für Benutzer Ihrer Klasse. Sie interagieren mit dem Auto, nicht mit seinen internen Teilen. Wenn Sie später eine andere Motor-Implementierung einsetzen, bleibt die öffentliche Schnittstelle des Autos gleich – nur die interne Delegation ändert sich.

challenge icon

Aufgabe

Einfach

Lass uns ein Musik-Player-System bauen, das Delegation demonstriert! Du wirst eine Speaker-Komponente und einen MusicPlayer erstellen, der diese enthält. Der Player wird die Soundausgabe nicht direkt handhaben – stattdessen wird er diese Verantwortung an seinen internen Lautsprecher delegieren.

Du wirst deinen Code in drei Dateien organisieren:

  • Speaker.lua: Erstelle eine Speaker-Klasse mit einem Konstruktor :new(volume), der die Lautstärke speichert. Füge eine :playSound(trackName)-Methode hinzu, die Folgendes ausgibt: Playing "{trackName}" at volume {volume}
  • MusicPlayer.lua: Erstelle eine MusicPlayer-Klasse, deren Konstruktor :new(brand, speaker) einen Markennamen und ein Speaker-Objekt akzeptiert. Der Player speichert den Lautsprecher in sich selbst. Füge diese Methoden hinzu:
    • :play(trackName) — gibt {brand} player starting... aus und delegiert dann an die :playSound()-Methode des Lautsprechers
    • :stop() — gibt {brand} player stopped aus
  • main.lua: Bring alles zusammen! Lies die Eingaben für die Lautsprecherlautstärke, die Player-Marke und einen Tracknamen ein. Erstelle zuerst einen Speaker und übergib ihn dann an den MusicPlayer-Konstruktor. Rufe die :play()-Methode des Players mit dem Tracknamen auf und rufe anschließend :stop() auf.

Du wirst drei Eingaben erhalten:

  1. Die Lautsprecherlautstärke (eine Zahl)
  2. Die Marke des Musik-Players (ein String)
  3. Der Name des zu spielenden Tracks (ein String)

Deine Ausgabe sollte zeigen, wie der Player mit seinem Lautsprecher koordiniert:

{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stopped

Wenn die Eingaben zum Beispiel 75, SoundMax und Summer Vibes sind, sollte die Ausgabe wie folgt aussehen:

SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stopped

Beachte, dass der MusicPlayer nicht weiß, wie man Sound erzeugt – er weist einfach seinen Lautsprecher an, diesen Teil zu übernehmen. Das ist Delegation in Aktion: Das äußere Objekt bietet eine saubere Schnittstelle, während die innere Komponente die spezialisierte Arbeit erledigt!

Spickzettel

Delegation ermöglicht es einem äußeren Objekt, Methodenaufrufe an seine inneren Komponenten weiterzuleiten, wodurch Verantwortlichkeiten getrennt bleiben und saubere Schnittstellen entstehen.

Das äußere Objekt stellt einfache Methoden bereit, die die Arbeit an innere Objekte delegieren:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- An das innere Objekt delegieren
end

Das innere Objekt verarbeitet seine eigene spezialisierte Logik:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Ausgabe:
-- Turning the key...
-- Engine running at 250 HP

Vorteile der Delegation:

  • Die äußere Klasse muss nicht wissen, wie das innere Objekt funktioniert
  • Benutzer interagieren mit einer sauberen öffentlichen Schnittstelle
  • Interne Implementierungen können ausgetauscht werden, ohne die öffentliche Schnittstelle zu ändern

Probier es selbst

-- main.lua
-- Alles zusammenführen!

local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')

-- Eingaben einlesen
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()

-- TODO: Erstelle einen Speaker mit der angegebenen volume

-- TODO: Erstelle einen MusicPlayer mit brand und speaker

-- TODO: Rufe die play-Methode des Players mit dem trackName auf

-- TODO: Rufe die stop-Methode des Players auf
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming