Kapselung mit Closures
Verbergen Sie privaten Zustand mit objektorientierten Mustern auf Basis von Closures
Kapselung mit Closures ist eine kostenlose Lua Academy-Lektion auf CoddyKit. Dies ist Lektion 4 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.
Closure-basierte Objekte
Eine Alternative zur objektorientierten Programmierung mit Metatabellen: Verwenden Sie eine Closure, um den Zustand zu verbergen. Das Objekt ist eine Tabelle aus Funktionen; alle Funktionen schließen die privaten Variablen ein. Es ist keine Metatabelle erforderlich. Der private Zustand ist tatsächlich privat und von außen unerreichbar.
local function makeCounter(start)
local count = start or 0 -- truly private
return {
increment = function() count=count+1 end,
decrement = function() count=count-1 end,
get = function() return count end,
reset = function() count=0 end,
}
end
local c = makeCounter(10)
c.increment(); c.increment()
print(c.get()) -- 12
print(c.count) -- nil (truly private!)Privat und öffentlich
Bei Closures ist der Unterschied zwischen privat und öffentlich absolut: Closures teilen sich den Upvalue (privat), während externer Code nur die zurückgegebene Tabelle sieht (öffentlich). Es gibt keine Möglichkeit, auf private Variablen zuzugreifen, ohne die öffentliche API zu verwenden.
local function makeAccount(initial)
local balance = initial
local transactions = {}
local function record(type, amount)
transactions[#transactions+1] = {type=type,amount=amount}
end
return {
deposit = function(n) record("D",n); balance=balance+n end,
withdraw = function(n)
if n>balance then error("insufficient funds") end
record("W",n); balance=balance-n
end,
balance = function() return balance end,
history = function() return transactions end,
}
endGemeinsam verwendete Closures
Mehrere Funktionen in derselben zurückgegebenen Tabelle teilen sich dieselben Upvalues. So wird Zustand zwischen Methoden geteilt, ohne ihn öffentlich zugänglich zu machen. Alle Methoden sehen dieselben privaten Variablen.
local function makeQueue()
local items = {} -- shared by all methods
local size = 0
return {
enqueue = function(v) size=size+1; items[size]=v end,
dequeue = function()
if size==0 then return nil end
local head=1
while items[head]==nil do head=head+1 end
local v=items[head]; items[head]=nil; return v
end,
isEmpty = function() return size==0 end,
count = function() return size end,
}
endClosures und Metatabellen
Closures: tatsächlich privater Zustand, kein Overhead durch Metatabellen, aber jede Instanz besitzt eigene Funktionskopien (mehr Speicher). Metatabellen: gemeinsam genutzte Methoden (weniger Speicher), mit Debug-Werkzeugen inspizierbar und Unterstützung für Vererbung. Treffen Sie die Wahl abhängig von den Anforderungen an Datenschutz und der Anzahl der Instanzen.
-- Closure: per-instance functions (more memory)
local function makePoint(x,y)
return {
x = function() return x end,
y = function() return y end,
distance = function()
return math.sqrt(x*x+y*y)
end
}
end
-- Metatable: shared methods (less memory)
-- local Point = {}; Point.__index = Point
-- function Point.new(x,y) return setmetatable({x=x,y=y},Point) endVeränderliche Closures
Closures über veränderlichen Variablen ermöglichen es, zustandsbehaftete Objekte ganz ohne Tabellen zu erstellen. Eine einzelne Closure kann Zustand speichern und Ergebnisse berechnen.
local function makeAccumulator()
local sum, count = 0, 0
return {
add = function(n) sum=sum+n; count=count+1 end,
mean = function()
return count>0 and sum/count or 0
end,
total = function() return sum end,
n = function() return count end,
}
end
local acc = makeAccumulator()
for _, v in ipairs({10,20,30,40,50}) do
acc.add(v)
end
print(acc.total(),acc.mean(),acc.n()) -- 150 30.0 5Konstruktor mit Validierung
Konstruktoren auf Closure-Basis validieren in der Factory-Funktion und nicht in einer Methode. Ungültige Eingaben führen dazu, dass die Factory nil oder einen Fehler zurückgibt, bevor ein Objekt erstellt wird.
local function makeRange(lo, hi)
assert(lo<=hi,"lo must be <= hi")
return {
contains = function(v) return v>=lo and v<=hi end,
clamp = function(v) return math.max(lo,math.min(hi,v)) end,
lo = function() return lo end,
hi = function() return hi end,
span = function() return hi-lo end,
}
end
local r = makeRange(0,100)
print(r.contains(50)) -- true
print(r.clamp(150)) -- 100Ereignisse mit Closures
Ein mit Closures implementierter Event Emitter: Die Liste der Handler ist privat; add/remove/emit bilden die öffentliche API.
local function makeEmitter()
local handlers = {}
return {
on = function(event, fn)
handlers[event] = handlers[event] or {}
handlers[event][#handlers[event]+1] = fn
end,
emit = function(event, ...)
for _, fn in ipairs(handlers[event] or {}) do
fn(...)
end
end,
off = function(event) handlers[event] = {} end,
}
end
local emitter = makeEmitter()
emitter.on("data", function(v) print("Got:", v) end)
emitter.emit("data", 42) -- Got: 42Memoization mit Closures
Ein Memoize-Wrapper mithilfe von Closures: Der Cache und die umschlossene Funktion sind privat; zurückgegeben wird nur die memoizierte Version.
local function memoize(fn)
local cache = {}
return function(...)
local key = table.concat({...}, ",")
if cache[key] == nil then
cache[key] = fn(...)
end
return cache[key]
end
end
local expensiveFib
expensiveFib = memoize(function(n)
if n<=1 then return n end
return expensiveFib(n-1)+expensiveFib(n-2)
end)
for i=0,10 do io.write(expensiveFib(i).." ") end
print()Closure-Objekte erweitern
Sie können ein Closure-basiertes Objekt erweitern, indem Sie ein neues Objekt erstellen, das die Methoden des ursprünglichen Objekts aufruft. Das ähnelt Wrapping, nicht Vererbung — an das ursprüngliche Objekt wird delegiert.
local function makeTimedCounter(start)
local base = makeCounter and makeCounter(start) or (function()
local c=start or 0
return {inc=function()c=c+1 end,get=function()return c end}
end)()
local callCount = 0
return {
increment = function()
callCount=callCount+1
base.inc()
end,
get = base.get,
calls = function() return callCount end,
}
endWann Sie Closures verwenden sollten
Verwenden Sie Closure-basierte objektorientierte Programmierung, wenn Sie tatsächlich privaten und geschützten Zustand benötigen, nur wenige Instanzen haben (Speicher keine große Rolle spielt) oder Code im funktionalen Stil schreiben. Verwenden Sie Metatabellen, wenn Sie Vererbung oder viele Instanzen benötigen oder OOP-Bibliotheken integrieren möchten.
-- Guideline summary:
-- Closures: true privacy, no metatable, self-contained
-- Metatables: shared methods, inheritance, instanceof checks
-- Rule of thumb:
-- < 100 instances with private state -> closures
-- > 100 instances OR need inheritance -> metatables
print("Both patterns are valid Lua OOP.")Kurztest
Was ist der wichtigste Vorteil von Closure-basierten Objekten gegenüber Objekten auf Metatabellenbasis?
Zusammenfassung: Kapselung mit Closures
Zusammenfassung:
- Closure-Muster: Eine Factory-Funktion gibt eine Methodentabelle zurück; der Zustand ist ein Upvalue
- Tatsächlich privat: Kein Zugriff auf Upvalues von außen möglich
- Alle zurückgegebenen Methoden teilen sich dieselben privaten Upvalues
- Kompromiss: mehr Speicher pro Instanz gegenüber besserem Schutz der Privatsphäre
- Verwenden Sie dies für sicherheitskritischen Code oder funktionale Entwürfe
Lerne Lua mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 40
- Lektionen
- 159
Häufig gestellte Fragen
Ist die Lektion „Kapselung mit Closures“ kostenlos?
Ja — der vollständige Text von „Kapselung mit Closures“ 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 „Kapselung mit Closures“?
Verbergen Sie privaten Zustand mit objektorientierten Mustern auf Basis von Closures 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 4 von 4.
Wie lange dauert die Lektion „Kapselung mit Closures“?
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
- Klassen über Metatabellen
- Konstruktoren und new()
- Instanzmethoden und self
- Kapselung mit Closures