Has-A-Beziehung
Teil des Abschnitts Object Oriented Programming der Lua-Journey von Coddy — Lektion 49 von 70.
In diesem Kurs hast du bisher Vererbung genutzt, um Verhalten zwischen Klassen zu teilen – ein Dog „is an“ Animal. Aber Vererbung ist nicht immer das richtige Werkzeug.
Manchmal teilen Objekte keinen Stammbaum; stattdessen enthält ein Objekt einfach ein anderes. Dies wird als Komposition bezeichnet und bildet eine „has-a“-Beziehung (hat-ein) ab.
Betrachten wir ein Auto. Ein Auto ist kein Typ von Motor – es hat einen Motor. Der Motor ist ein separates Objekt, das sich im Inneren des Autos befindet:
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 innerhalb von Car
}
setmetatable(obj, Car)
return obj
endBeim Erstellen eines Autos übergeben Sie ein vorhandenes Motor-Objekt an dessen Konstruktor:
local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)
print(myCar.engine.horsepower) -- 200Das Auto erbt nicht vom Motor – es hält lediglich eine Referenz auf einen. Dies hält beide Klassen unabhängig. Sie könnten einen anderen Motor einbauen oder dieselbe Motorklasse in einem Motorrad verwenden.
Komposition bietet Ihnen eine Flexibilität, die Vererbung nicht bieten kann: Sie setzen Objekte aus Einzelteilen zusammen, anstatt sie in eine starre Familienhierarchie zu zwängen.
Aufgabe
EinfachLassen Sie uns ein Computersystem mittels Komposition bauen! Anstelle von Vererbung erstellen Sie einen Computer, der eine CPU in sich hat – was die "hat-ein"-Beziehung demonstriert.
Sie werden Ihren Code über drei Dateien organisieren:
CPU.lua: Erstellen Sie eine CPU-Klasse mit einem Konstruktor:new(brand, speed), der den Markennamen und die Geschwindigkeit in GHz speichert. Fügen Sie eine:getInfo()-Methode hinzu, die einen String im Format{brand} @ {speed}GHzzurückgibt.Computer.lua: Erstellen Sie eine Computer-Klasse, deren Konstruktor:new(model, cpu)einen Modellnamen und ein CPU-Objekt akzeptiert. Der Computer speichert das CPU-Objekt in sich selbst (Komposition!). Fügen Sie eine:describe()-Methode hinzu, die das Modell des Computers und die Informationen seiner CPU ausgibt.main.lua: Bringen Sie alles zusammen! Lesen Sie Eingaben für die CPU-Marke, die CPU-Geschwindigkeit und das Computermodell ein. Erstellen Sie zuerst ein CPU-Objekt und übergeben Sie es dann an den Computer-Konstruktor. Rufen Sie schließlich die:describe()-Methode des Computers auf.
Sie erhalten drei Eingaben:
- Die CPU-Marke (ein String)
- Die CPU-Geschwindigkeit in GHz (eine Zahl)
- Der Name des Computermodells (ein String)
Ihre Ausgabe sollte die Beschreibung des Computers anzeigen, die Informationen aus der enthaltenen CPU enthält:
Model: {model}
CPU: {brand} @ {speed}GHzWenn die Eingaben beispielsweise Intel, 3.5 und WorkStation sind, sollte die Ausgabe wie folgt aussehen:
Model: WorkStation
CPU: Intel @ 3.5GHzBeachten Sie, dass der Computer nicht von der CPU erbt – er hält einfach eine Referenz auf eine solche. Die :describe()-Methode des Computers greift über das gespeicherte Objekt auf die Daten der CPU zu und zeigt so, wie Komposition es ermöglicht, komplexe Objekte aus einfacheren Teilen aufzubauen!
Spickzettel
Objekte können durch Komposition in Beziehung stehen, was eine „hat-ein“-Beziehung (has-a) modelliert. Anstelle von Vererbung enthält ein Objekt ein anderes als Komponente.
Beispiel für Komposition mit einem Auto, das einen Motor hat:
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 innerhalb von Car
}
setmetatable(obj, Car)
return obj
endErstellen und Verwenden von zusammengesetzten Objekten:
local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)
print(myCar.engine.horsepower) -- 200Komposition bietet Flexibilität, indem Objekte aus Teilen zusammengesetzt werden, anstatt starre Vererbungshierarchien zu verwenden. Komponenten bleiben unabhängig und können über verschiedene Klassen hinweg wiederverwendet werden.
Probier es selbst
-- main.lua
-- Alles mittels Komposition zusammenführen
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 Object Oriented Programming
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-Klasse2Klassen-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