Metody a self

V zápisu farma.popis(farma) píšete farma dvakrát: jednou, abyste našli funkci, a podruhé, abyste jí farmu předali. Objekty se takhle používají pořád, a tak má Lua zkratku, dvojtečku:

local farma = {nazev = "Farma Slunečnice", mince = 120}

function farma.popis(f)
    print(f.nazev .. ": " .. f.mince .. " mincí")
end

farma:popis()

Vypíše:

Farma Slunečnice: 120 mincí

farma:popis() je zkratka pro farma.popis(farma): Lua vezme funkci z tabulky a jako první argument jí předá samotnou tabulku. Další argumenty následují za ní: farma:vydelej(30) znamená farma.vydelej(farma, 30).

Dvojtečku můžete použít i při definici funkce. function farma:vydelej(castka) je zkratka pro function farma.vydelej(self, castka): Lua přidá skrytý první parametr jménem self (anglicky „sám“). Když funkci zavoláte s dvojtečkou, je v self tabulka, na které jste ji zavolali:

local mrkev = {nazev = "Mrkev", vek = 0, dny = 3}

function mrkev:dalsiDen()
    self.vek = self.vek + 1
end

function mrkev:jeZrala()
    return self.vek >= self.dny
end

mrkev:dalsiDen()
mrkev:dalsiDen()
print(mrkev.vek, mrkev:jeZrala())
mrkev:dalsiDen()
print(mrkev.vek, mrkev:jeZrala())

Vypíše:

2	false
3	true

Ve volání mrkev:dalsiDen() je self mrkev, takže self.vek = self.vek + 1 přidá mrkvi jeden den. Funkci v objektu, která dostává objekt jako self, se říká metoda a mrkev:dalsiDen() je volání metody. Uvnitř metody používejte vždy self, ne název tabulky. Pak bude stejná metoda fungovat pro každou tabulku, na které ji zavoláte, a to budete potřebovat hned v příštím cvičení.

Texty fungují stejně. V lekci o řetězcích jste se dozvěděli, že s:upper() je zkratka pro string.upper(s). Teď už víte, co dělá dvojtečka: s:upper() je s.upper(s), volání metody s textem jako prvním argumentem:

local s = "mrkev"
print(s:upper(), s.upper(s), string.upper(s))

Vypíše:

MRKEV	MRKEV	MRKEV

Jak text najde funkci upper v tabulce string, uvidíte ve cvičení o metatabulkách.

Klasická chyba: tečka místo dvojtečky. Metodu definovanou s dvojtečkou musíte s dvojtečkou i volat. S tečkou jí Lua tabulku nepředá a self je nil:

local mrkev = {nazev = "Mrkev", vek = 0, dny = 3}

function mrkev:dalsiDen()
    self.vek = self.vek + 1
end

mrkev.dalsiDen()

Program skončí chybou:

main.lua:4: attempt to index a nil value (local 'self')
stack traceback:
	main.lua:4: in field 'dalsiDen'
	main.lua:7: in main chunk

První řádek ukazuje na řádek 4 uvnitř metody, kde se self používá. Chyba je ale v řádku, který metodu zavolal, a ten najdete na konci výpisu: main.lua:7. Údaj in field 'dalsiDen' prozrazuje, že funkce byla zavolána s tečkou; při volání s dvojtečkou by tam stálo in method 'dalsiDen'. Kdykoli chybová hláška zmiňuje (local 'self'), hledejte tečku, která má být dvojtečkou.

Opačná chyba je funkce definovaná s tečkou, function mrkev.dalsiDen(dny), a zavolaná s dvojtečkou, mrkev:dalsiDen(2). Dvojtečka předá jako první argument tabulku, takže v dny bude mrkev a dvojka se zahodí. Pravidlo je jednoduché: metody definujte s dvojtečkou a volejte je s dvojtečkou.

Pokyny

Udělejte z obou funkcí metody: definujte je s dvojtečkou, function stodola:vypis() a function stodola:pridejVejce(pocet), uvnitř používejte self a volejte je s dvojtečkou. Program vypíše totéž co předtím.

Přidejte metodu stodola:prodejVejce(pocet), která ze stodoly odebere pocet vajec a vrátí, kolik za ně Ema dostane mincí: 2 mince za vejce. Na konci programu prodejte 10 vajec, vypište utržené mince a znovu obsah stodoly:

Stodola: 12 vajec, 4 litry mléka
Stodola: 18 vajec, 4 litry mléka
Prodáno 10 vajec za 20 mincí
Stodola: 8 vajec, 4 litry mléka

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

2/9