Methoden und self
In hof.beschreiben(hof) schreibst du hof zweimal: einmal, um die Funktion zu finden, und einmal, um ihr den Hof zu geben. Objekte werden ständig so benutzt, deshalb hat Lua eine Abkürzung, den Doppelpunkt:
local hof = {name = "Sonnenblumenhof", muenzen = 120}
function hof.beschreiben(h)
print(h.name .. ": " .. h.muenzen .. " Münzen")
end
hof:beschreiben()Das gibt Folgendes aus:
Sonnenblumenhof: 120 Münzenhof:beschreiben() ist die Kurzform von hof.beschreiben(hof): Lua holt die Funktion aus der Tabelle und übergibt ihr die Tabelle selbst als erstes Argument. Weitere Argumente folgen danach: hof:verdienen(30) bedeutet hof.verdienen(hof, 30).
Der Doppelpunkt funktioniert auch beim Definieren einer Funktion. function hof:verdienen(betrag) ist die Kurzform von function hof.verdienen(self, betrag): Lua fügt einen versteckten ersten Parameter namens self hinzu. Rufst du die Funktion mit einem Doppelpunkt auf, ist self die Tabelle, auf der du sie aufgerufen hast:
local karotte = {name = "Karotte", alter = 0, tage = 3}
function karotte:wachsen()
self.alter = self.alter + 1
end
function karotte:istReif()
return self.alter >= self.tage
end
karotte:wachsen()
karotte:wachsen()
print(karotte.alter, karotte:istReif())
karotte:wachsen()
print(karotte.alter, karotte:istReif())Das gibt Folgendes aus:
2 false
3 trueIn karotte:wachsen() ist self die karotte, und self.alter = self.alter + 1 macht die Karotte einen Tag älter. Eine Funktion in einem Objekt, die das Objekt als self bekommt, heißt Methode, und karotte:wachsen() ist ein Methodenaufruf. Benutze in einer Methode immer self, nicht den Namen der Tabelle. Dann funktioniert dieselbe Methode für jede Tabelle, auf der du sie aufrufst, und das brauchst du in der nächsten Übung.
Mit Texten ist es genauso. In der Lektion über Zeichenketten hast du gelernt, dass s:upper() die Kurzform von string.upper(s) ist. Jetzt weißt du, was der Doppelpunkt tut: s:upper() ist s.upper(s), ein Methodenaufruf mit dem Text als erstem Argument:
local s = "karotte"
print(s:upper(), s.upper(s), string.upper(s))Das gibt Folgendes aus:
KAROTTE KAROTTE KAROTTEWie ein Text upper in der Tabelle string findet, siehst du in der Übung über Metatabellen.
Der klassische Fehler: ein Punkt statt eines Doppelpunkts. Eine Methode, die mit einem Doppelpunkt definiert wurde, muss auch mit einem Doppelpunkt aufgerufen werden. Mit einem Punkt übergibt Lua die Tabelle nicht, und self ist nil:
local karotte = {name = "Karotte", alter = 0, tage = 3}
function karotte:wachsen()
self.alter = self.alter + 1
end
karotte.wachsen()Das Programm endet mit einem Fehler:
main.lua:4: attempt to index a nil value (local 'self')
stack traceback:
main.lua:4: in field 'wachsen'
main.lua:7: in main chunkDie erste Zeile zeigt auf Zeile 4, in der Methode, wo self benutzt wird. Der Fehler liegt aber in der Zeile, die die Methode aufgerufen hat, der letzten im Traceback: main.lua:7. in field 'wachsen' sagt dir, dass die Funktion mit einem Punkt aufgerufen wurde; bei einem Aufruf mit Doppelpunkt stünde dort in method 'wachsen'. Wenn ein Fehler (local 'self') erwähnt, suche nach einem Punkt, der ein Doppelpunkt sein sollte.
Der umgekehrte Fehler ist eine Funktion, die mit einem Punkt definiert, function karotte.wachsen(tage), und mit einem Doppelpunkt aufgerufen wird, karotte:wachsen(2). Der Doppelpunkt übergibt die Tabelle als erstes Argument, also bekommt tage die Karotte, und die 2 wird ignoriert. Die Regel ist einfach: Definiere Methoden mit einem Doppelpunkt und rufe sie mit einem Doppelpunkt auf.
So schreibst du es:
Anweisungen
- 1
Mache aus beiden Funktionen Methoden: Definiere sie mit einem Doppelpunkt,
function scheune:ausgeben()undfunction scheune:eierHinzufuegen(anzahl), benutze darinselfund rufe sie mit einem Doppelpunkt auf. Das Programm gibt dasselbe aus wie vorher. - 2
Füge eine Methode
scheune:eierVerkaufen(anzahl)hinzu, dieanzahlEier aus der Scheune nimmt und zurückgibt, wie viele Münzen sie einbringen: 2 Münzen pro Ei. Verkaufe am Ende des Programms 10 Eier, gib die Münzen aus und gib den Bericht noch einmal aus:Scheune: 12 Eier, 4 Liter Milch Scheune: 18 Eier, 4 Liter Milch 10 Eier für 20 Münzen verkauft Scheune: 8 Eier, 4 Liter Milch