Anwendung mehrerer Mixins
Teil des Abschnitts Object Oriented Programming der Lua-Journey von Coddy — Lektion 52 von 70.
Ein einzelnes Mixin fügt einer Klasse eine Reihe von Verhaltensweisen hinzu. Aber reale Objekte benötigen oft Fähigkeiten aus mehreren Quellen. Ein Spielobjekt muss sich möglicherweise bewegen und auf dem Bildschirm sichtbar sein – zwei separate Anliegen, die nicht in dasselbe Mixin gehören.
Die Lösung ist unkompliziert: Wenden Sie mehrere Mixins auf dieselbe Klasse an. Jedes Mixin steuert seine eigenen Methoden bei, und die Klasse verfügt am Ende über alle:
local Movable = {}
function Movable:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
local Visible = {}
function Visible:show()
print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
print("Hidden")
endWenden Sie beide Mixins mit derselben Hilfsfunktion von zuvor auf Ihre Klasse an:
local function applyMixin(class, mixin)
for key, value in pairs(mixin) do
class[key] = value
end
end
local GameObject = {}
GameObject.__index = GameObject
applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)Jetzt können GameObject-Instanzen sich sowohl bewegen als auch selbst darstellen:
local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show() -- Anzeigen bei 5, 3Ein Hinweis zur Vorsicht: Wenn zwei Mixins denselben Methodennamen definieren, überschreibt das zweite angewendete Mixin das erste. Halten Sie Ihre Mixin-Methoden eindeutig, um unerwartetes Verhalten zu vermeiden.
Aufgabe
EinfachLassen Sie uns eine Character-Klasse für ein Spiel erstellen, die mithilfe von Mixins mehrere Fähigkeiten kombiniert! Ihr Charakter wird in der Lage sein, sowohl Feinde anzugreifen als auch sich selbst zu heilen – zwei unterschiedliche Verhaltensweisen, die aus separaten Mixins stammen.
Sie werden Ihren Code über vier Dateien organisieren:
Attacker.lua: Erstellen Sie ein Mixin mit einer:attack(targetName)-Methode, die{self.name} attacks {targetName} for {self.damage} damage!ausgibt (setzt voraus, dass das Objekt die Feldernameunddamagebesitzt).Healer.lua: Erstellen Sie ein Mixin mit einer:heal(amount)-Methode, die den Betrag zuself.healthaddiert und{self.name} heals for {amount}. Health: {newHealth}ausgibt.Character.lua: Erstellen Sie eine Character-Klasse mit einem Konstruktor:new(name, health, damage), der alle drei Attribute speichert. Wenden Sie sowohl das Attacker- als auch das Healer-Mixin an, damit jeder Charakter angreifen und heilen kann. Fügen Sie eine:status()-Methode hinzu, die{name} - Health: {health}, Damage: {damage}ausgibt.main.lua: Schreiben Sie hier die HilfsfunktionapplyMixin. Lesen Sie Eingaben für den Namen eines Charakters, die Gesundheit, den Schaden, ein Ziel zum Angreifen und einen Heilungsbetrag ein. Erstellen Sie einen Character, zeigen Sie seinen Status an, lassen Sie ihn das Ziel angreifen, sich selbst heilen und zeigen Sie dann erneut seinen Status an.
Sie erhalten fünf Eingaben:
- Charaktername (ein String)
- Anfangsgesundheit (eine Zahl)
- Schadenswert (eine Zahl)
- Zielname zum Angreifen (ein String)
- Heilungsbetrag (eine Zahl)
Ihre Ausgabe sollte zeigen, wie der Charakter beide Mixin-Fähigkeiten nutzt:
{name} - Health: {health}, Damage: {damage}
{name} attacks {target} for {damage} damage!
{name} heals for {healAmount}. Health: {newHealth}
{name} - Health: {newHealth}, Damage: {damage}Wenn die Eingaben beispielsweise Warrior, 100, 25, Goblin und 30 sind, sollte die Ausgabe wie folgt aussehen:
Warrior - Health: 100, Damage: 25
Warrior attacks Goblin for 25 damage!
Warrior heals for 30. Health: 130
Warrior - Health: 130, Damage: 25Jedes Mixin steuert seine eigene Methode zur Character-Klasse bei. Der Charakter erbt nicht von einem der Mixins – er erhält seine Fähigkeiten einfach über die Funktion applyMixin. Das ist die Stärke der Kombination mehrerer Mixins!
Spickzettel
Mehrere Mixins können auf eine einzelne Klasse angewendet werden, um verschiedene Verhaltensweisen zu kombinieren. Jedes Mixin steuert seine eigenen Methoden zur Klasse bei.
Definieren Sie separate Mixins für verschiedene Belange:
local Movable = {}
function Movable:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
local Visible = {}
function Visible:show()
print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
print("Hidden")
endWenden Sie mehrere Mixins auf eine Klasse an, indem Sie die Hilfsfunktion applyMixin verwenden:
local function applyMixin(class, mixin)
for key, value in pairs(mixin) do
class[key] = value
end
end
local GameObject = {}
GameObject.__index = GameObject
applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)Die Klasse verfügt nun über Methoden von allen angewendeten Mixins:
local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show() -- Zeigt an bei 5, 3Wichtig: Wenn zwei Mixins denselben Methodennamen definieren, überschreibt das zweite angewendete Mixin das erste. Halten Sie Methodennamen über Mixins hinweg eindeutig, um Konflikte zu vermeiden.
Probier es selbst
-- Hauptdatei
-- TODO: Schreibe die Hilfsfunktion applyMixin
-- Diese Funktion sollte alle Methoden von einer Mixin-Tabelle in eine Ziel-Tabelle kopieren
local function applyMixin(target, mixin)
-- TODO: Mixin-Anwendung implementieren
end
-- Mache applyMixin global verfügbar, damit Character.lua sie verwenden kann
_G.applyMixin = applyMixin
local Character = require('Character')
-- Eingaben lesen
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())
-- TODO: Erstelle einen Charakter mit dem angegebenen Namen, der Gesundheit und dem Schaden
-- TODO: Zeige den Status des Charakters an
-- TODO: Lasse den Charakter das Ziel angreifen
-- TODO: Lasse den Charakter sich selbst heilen
-- TODO: Zeige den Status des Charakters erneut an
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