Has-A-Beziehung
Teil des Abschnitts Objektorientierte Programmierung der Lua-Journey von Coddy. Lektion 49 von 70.
Im gesamten Kurs hast du Vererbung verwendet, um Verhalten zwischen Klassen zu teilen: Ein Dog „ist ein“ Animal. Aber Vererbung ist nicht immer das richtige Werkzeug.
Manchmal haben Objekte keinen gemeinsamen Stammbaum; stattdessen enthält ein Objekt einfach ein anderes. Dies wird als Komposition bezeichnet und bildet eine „hat-ein“-Beziehung ab.
Betrachte ein Auto. Ein Auto ist kein Motortyp. Es hat einen Motor. Der Motor ist ein separates Objekt, das im Auto existiert:
local Engine = {}
Engine.__index = Engine
function Engine:new(horsepower)
local obj = {horsepower = horsepower}
setmetatable(obj, Engine)
return obj
end
local Car = {}
Car.__index = Car
function Car:new(model, engine)
local obj = {
model = model,
engine = engine -- Speichere das Engine-Objekt in Car
}
setmetatable(obj, Car)
return obj
endBeim Erstellen eines Autos übergibst du seinem Konstruktor ein vorhandenes Motorobjekt:
local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)
print(myCar.engine.horsepower) -- 200Das Auto erbt nicht vom Motor. Es enthält lediglich eine Referenz auf ihn. Dadurch bleiben beide Klassen unabhängig. Du könntest einen anderen Motor einsetzen oder dieselbe Motorklasse in einem Motorrad verwenden.
Komposition gibt dir eine Flexibilität, die Vererbung nicht bieten kann: Du setzt Objekte aus Teilen zusammen, anstatt sie in eine starre Familienhierarchie einzubinden.
Aufgabe
EinfachErstellen wir ein Computersystem mithilfe von Komposition! Statt Vererbung erstellst du einen Computer, der eine enthaltene CPU besitzt: So wird die „has-a“-Beziehung veranschaulicht.
Du organisierst deinen Code auf drei Dateien verteilt:
CPU.lua: Erstelle eine CPU-Klasse mit einem Konstruktor:new(brand, speed), der den Markennamen und die Geschwindigkeit in GHz speichert. Füge eine:getInfo()-Methode hinzu, die eine Zeichenkette im folgenden Format zurückgibt:{brand} @ {speed}GHzComputer.lua: Erstelle eine Computer-Klasse, deren Konstruktor:new(model, cpu)einen Modellnamen und ein CPU-Objekt entgegennimmt. Der Computer speichert das CPU-Objekt in sich selbst (Komposition!). Füge eine:describe()-Methode hinzu, die das Modell des Computers und die Informationen seiner CPU ausgibt.main.lua: Führe alles zusammen! Lies Eingaben für die CPU-Marke, die CPU-Geschwindigkeit und das Computermodell ein. Erstelle zuerst ein CPU-Objekt und übergib es anschließend an den Computer-Konstruktor. Rufe schließlich die:describe()-Methode des Computers auf.
Du erhältst drei Eingaben:
- Die CPU-Marke (eine Zeichenkette)
- Die CPU-Geschwindigkeit in GHz (eine Zahl)
- Den Namen des Computermodells (eine Zeichenkette)
Deine Ausgabe sollte die Beschreibung des Computers anzeigen, die Informationen von seiner enthaltenen CPU umfasst:
Model: {model}
CPU: {brand} @ {speed}GHzWenn die Eingaben beispielsweise Intel, 3.5 und WorkStation lauten, sollte die Ausgabe wie folgt aussehen:
Model: WorkStation
CPU: Intel @ 3.5GHzBeachte, dass der Computer nicht von der CPU erbt. Er enthält lediglich eine Referenz auf eine CPU. Die :describe()-Methode des Computers greift über das gespeicherte Objekt auf die Daten der CPU zu und zeigt damit, wie du mithilfe von Komposition komplexe Objekte aus einfacheren Bestandteilen erstellen kannst!
Probier es selbst
-- main.lua
-- Alles mithilfe von Komposition zusammenbringen
local CPU = require('CPU')
local Computer = require('Computer')
-- Eingaben lesen
local cpuBrand = io.read()
local cpuSpeed = tonumber(io.read())
local computerModel = io.read()
-- TODO: Erstelle ein CPU-Objekt mit der Marke und der Geschwindigkeit
-- TODO: Erstelle ein Computer-Objekt mit dem Modell und dem CPU-Objekt
-- TODO: Rufe die describe()-Methode des Computers auf, um die Ausgabe zu drucken
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Das 'self'-Konzept
Tabellen mit FunktionenExplizites 'self'Die Doppelpunkt-SyntaxPunkt vs. DoppelpunktZusammenfassung – Beweglicher Punkt4Projekt: Digitale Bank
Projekt-SetupEinzahlungsmethode7Polymorphie & Überschreiben
Methoden überschreibenElternmethoden aufrufenDuck TypingGemeinsames InterfaceTyp prüfenRückblick - Mitarbeiterrollen10Projekt: Formen-Manager
Projekt-SetupRechteck-KlasseKreis-KlasseUmfang-MethodeFormen-SammlungGesamtflächeFormen filtern2Klassen-Prototyp-Muster
Das Prototyp-KonzeptVerknüpfung mit __indexDer :new()-KonstruktorAttribute initialisierenUnabhängige InstanzenZusammenfassung – Autofabrik5Operatorüberladung in OOP
Objekte addierenObjekte subtrahierenObjekte verkettenObjekte vergleichen (<, >)Rückblick – Wallet-Mathematik3Objektzustand und -verhalten
InstanzvariablenGetter-MethodenSetter-MethodenBerechnete EigenschaftenStrings formatierenGleichheitsprüfungenZusammenfassung – Studentennote6Grundlagen der Vererbung
Das Vererbungs-SetupMethoden vererbenDen Konstruktor erweiternChild-Methoden hinzufügenGemeinsam vs. EinzigartigZusammenfassung - Formen-Hierarchie9Komposition & Mixins
Has-A-BeziehungDelegationEinfache MixinsAnwendung mehrerer MixinsMixins vs. VererbungZusammenfassung – Roboter-Montage12Abschluss-Herausforderungen
Wiederholung - InventarsystemWiederholung - BenutzerverwaltungWiederholung - Score-TrackerFinaler OOP-CheckÜbe selbstständig: Online-Lua-Compiler