Mixin-Muster
Setzen Sie Verhalten zusammen, indem Sie Methoden aus mehreren Quelltabellen kopieren
Mixin-Muster ist eine kostenlose Lua Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Lua Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist ein Mixin?
Ein Mixin ist eine Tabelle mit Methoden, die in mehrere Klassen kopiert werden können. Im Gegensatz zur Vererbung fügen Mixins Verhalten hinzu, ohne eine Eltern-Kind-Beziehung herzustellen. Eine Klasse kann Verhalten aus mehreren Mixins kombinieren.
local Flyable={}
function Flyable:fly()
print(self.name.." is flying!")
end
function Flyable:land()
print(self.name.." landed.")
end
local Bird={} Bird.__index=Bird
-- Mix in Flyable
for k,v in pairs(Flyable) do Bird[k]=v end
function Bird.new(name)
return setmetatable({name=name},Bird)
end
Bird.new("Eagle"):fly()Mehrere Mixins
Wenden Sie mehrere Mixins auf eine Klasse an, um komplexes Verhalten aus einfachen Bausteinen zusammenzusetzen. Dies ist eine horizontale Komposition – jedes Mixin ist unabhängig.
local Serializable={}
function Serializable:toCSV(fields)
local row={}
for _,f in ipairs(fields) do row[#row+1]=tostring(self[f]) end
return table.concat(row,",")
end
local Loggable={}
function Loggable:log(msg)
print("["..os.date("%H:%M").."]["..self.name.."] "..msg)
end
local Entity={} Entity.__index=Entity
for k,v in pairs(Serializable) do Entity[k]=v end
for k,v in pairs(Loggable) do Entity[k]=v end
function Entity.new(n,v) return setmetatable({name=n,value=v},Entity) end
local e=Entity.new("item",42)
e:log("created"); print(e:toCSV({"name","value"}))Mixin-Konflikte
Wenn zwei Mixins denselben Methodennamen definieren, setzt sich das zuletzt angewendete durch. Lösen Sie Konflikte ausdrücklich, indem Sie entscheiden, welche Version des Mixins beibehalten werden soll, oder kapseln Sie beide Versionen, um sie beide aufzurufen.
local A={speak=function(self) print(self.name.." (A)") end}
local B={speak=function(self) print(self.name.." (B)") end}
local C={} C.__index=C
for k,v in pairs(A) do C[k]=v end
for k,v in pairs(B) do C[k]=v end -- B.speak overwrites A.speak
-- Explicit resolution:
local origA, origB = A.speak, B.speak
function C:speak() origA(self); origB(self) end -- call both
local c=setmetatable({name="X"},C)
c:speak()include()-Hilfsfunktion
Eine Hilfsfunktion vereinfacht das Anwenden von Mixins: include(Class, Mixin) kopiert die Mixin-Methoden in die Klasse und überspringt Felder, die bereits vorhanden sind (dadurch werden bestehende Methoden nicht überschrieben).
local function include(cls, mixin)
for k, v in pairs(mixin) do
if cls[k] == nil then
cls[k] = v
end
end
return cls
end
local Comparable={
equals=function(a,b) return a:compareTo(b)==0 end,
lt=function(a,b) return a:compareTo(b)<0 end,
}
local Temp={} Temp.__index=Temp
include(Temp, Comparable)
function Temp.new(c) return setmetatable({c=c},Temp) end
function Temp:compareTo(other) return self.c-other.c end
local a,b=Temp.new(100),Temp.new(50)
print(b.lt and b:lt(a)) -- true (b < a)Mixin mit Zustand
Mixins, die einen Zustand pro Instanz benötigen, initialisieren ihn in der init-Funktion des Mixins. Der Klassenkonstruktor ruft die init-Funktionen der Mixins auf, um den Zustand jedes Mixins in der Instanz einzurichten.
local Observable={}
function Observable._init(self)
self._listeners={}
end
function Observable:on(event,fn)
self._listeners[event]=self._listeners[event] or {}
self._listeners[event][#self._listeners[event]+1]=fn
end
function Observable:emit(event,...)
for _,fn in ipairs(self._listeners[event] or {}) do fn(...) end
end
local Button={} Button.__index=Button
for k,v in pairs(Observable) do Button[k]=v end
function Button.new(label)
local self=setmetatable({label=label},Button)
Observable._init(self)
return self
end
local btn=Button.new("OK")
btn:on("click",function() print("Clicked!") end)
btn:emit("click")Mixin-Module
Packen Sie das Verhalten eines Mixins in separate Moduldateien. Binden Sie diese im Klassenmodul ein und wenden Sie sie an. So bleibt jeder Verhaltensaspekt in einer eigenen Datei, und die Codebasis bleibt übersichtlich.
-- In a real project:
-- local Loggable = require("mixins.loggable")
-- local Cacheable = require("mixins.cacheable")
-- local MyClass = {}
-- for k,v in pairs(Loggable) do MyClass[k]=v end
-- for k,v in pairs(Cacheable) do MyClass[k]=v end
local TimestampMixin={}
function TimestampMixin:setCreated() self.createdAt=os.time() end
function TimestampMixin:age() return os.time()-self.createdAt end
local Record={} Record.__index=Record
for k,v in pairs(TimestampMixin) do Record[k]=v end
function Record.new(data)
local self=setmetatable(data or {},Record)
self:setCreated()
return self
end
print(Record.new({}).createdAt>0)Rollenbasierte Mixins
Weisen Sie Objekten zur Laufzeit Rollen zu, indem Sie Mixin-Funktionen gezielt anwenden. Dadurch lässt sich das Verhalten pro Instanz statt pro Klasse konfigurieren.
local Roles={}
Roles.admin={deleteUser=function(self) print(self.name.." deletes user") end}
Roles.editor={editPost=function(self) print(self.name.." edits post") end}
Roles.viewer={viewPost=function(self) print(self.name.." views post") end}
local User={} User.__index=User
function User.new(name,...)
local self=setmetatable({name=name},User)
for _,role in ipairs({...}) do
for k,v in pairs(Roles[role] or {}) do self[k]=v end
end
return self
end
local alice=User.new("Alice","admin","editor")
alice:deleteUser(); alice:editPost()Anwendung von Mixins prüfen
Verfolgen Sie mit einer Menge, welche Mixins auf eine Klasse angewendet wurden. So verhindern Sie eine doppelte Anwendung und können die Fähigkeiten einer Klasse untersuchen.
local function applyMixin(cls, mixin, name)
cls._mixins = cls._mixins or {}
if cls._mixins[name] then return end -- already applied
for k,v in pairs(mixin) do
if k~="_init" then cls[k]=cls[k] or v end
end
cls._mixins[name] = true
end
local Fly={fly=function(self) print(self.name.." flies") end}
local Bird={} Bird.__index=Bird
applyMixin(Bird,Fly,"Fly")
applyMixin(Bird,Fly,"Fly") -- no-op, already applied
print(Bird._mixins.Fly) -- trueMixins vs. Vererbung vs. Komposition
Drei Arten der Komposition: Vererbung (ist-ein, strenge Hierarchie), Mixins (Methoden kopieren, flach) und Komposition (hat-ein, Delegation). Wählen Sie je nach Beziehung: Ein Tier IST EIN Lebewesen (Vererbung), ein Lebewesen KANN fliegen (Mixin), ein Auto HAT einen Motor (Komposition).
-- Inheritance: "is-a"
-- local Dog = extends(Animal)
-- Mixin: "can-do"
-- include(Dog, Swimmable)
-- Composition: "has-a"
-- local Dog = {}
-- function Dog.new()
-- return {collar=Collar.new(),chip=Chip.new()}
-- end
print("Pick the right tool for the relationship")Mixin-Vorlage
Eine standardisierte Mixin-Vorlage: Die Mixin-Tabelle enthält Methoden, optional ein _init für den Zustand pro Instanz und ein Namensfeld zur Konflikterkennung. Ein einheitliches Muster macht Mixins projektübergreifend kombinierbar.
-- Standard mixin template:
local EventMixin = {}
EventMixin._name = "EventMixin"
function EventMixin._init(self)
self._events = {}
end
function EventMixin:on(e, fn)
self._events[e] = self._events[e] or {}
self._events[e][#self._events[e]+1] = fn
end
function EventMixin:trigger(e, ...)
for _, fn in ipairs(self._events[e] or {}) do fn(...) end
end
-- return EventMixin
print("EventMixin ready for use")Mixin-Frage
Wie wenden Sie ein Mixin auf eine Klasse an?
Zusammenfassung: Mixin-Muster
Mixins kopieren Methoden aus einer Quelltabelle in die Zielklasse und setzen so Verhalten ohne Vererbung zusammen. Verwenden Sie sie für querschnittliche Belange wie Serialisierung, Protokollierung und Ereignisverarbeitung.
Häufig gestellte Fragen
Ist die Lektion „Mixin-Muster“ kostenlos?
Ja — der vollständige Text von „Mixin-Muster“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Lua Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Mixin-Muster“?
Setzen Sie Verhalten zusammen, indem Sie Methoden aus mehreren Quelltabellen kopieren Du übst Lua Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Lua Academy zu starten?
Keine Vorkenntnisse erforderlich. Lua Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Mixin-Muster“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Lua Academy-Lektion Code schreiben und ausführen?
Ja. Jede Lua Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Einfache Vererbung mit __index-Verkettung
- Elternmethoden mit super aufrufen
- Mixin-Muster
- Überschreiben und Polymorphismus