Operátory
I s operátory můžou objekty pracovat. Normálně se == mezi dvěma tabulkami ptá, jestli jde o tutéž tabulku (jak jste viděli v lekci o tabulkách jako slovnících, {} == {} je false), a < nebo + mezi tabulkami skončí chybou. Metametody vám dovolí určit, co mají tyto operátory s vašimi objekty dělat. Tady je třída pro pytle se sklizenou úrodou:
local Pytel = {}
Pytel.__index = Pytel
function Pytel.new(plodina, kg)
local pytel = {plodina = plodina, kg = kg}
setmetatable(pytel, Pytel)
return pytel
end
function Pytel:__tostring()
return self.plodina .. ": " .. self.kg .. " kg"
end
function Pytel.__add(a, b)
return Pytel.new(a.plodina, a.kg + b.kg)
end
function Pytel.__eq(a, b)
return a.plodina == b.plodina and a.kg == b.kg
end
function Pytel.__lt(a, b)
return a.kg < b.kg
end
local brambory = Pytel.new("Brambory", 20)
local dalsiBrambory = Pytel.new("Brambory", 15)
local mrkev = Pytel.new("Mrkev", 20)
print(brambory + dalsiBrambory)
print(brambory == mrkev, brambory == Pytel.new("Brambory", 20))
print(dalsiBrambory < brambory, dalsiBrambory > brambory)
local pytle = {Pytel.new("Dýně", 40), mrkev, dalsiBrambory}
table.sort(pytle)
for _, pytel in ipairs(pytle) do
print(pytel)
endVypíše:
Brambory: 35 kg
false true
true false
Brambory: 15 kg
Mrkev: 20 kg
Dýně: 40 kgMetametoda operátoru dostane obě strany, a zleva a b zprava, a výsledkem operátoru je to, co vrátí. Proto se tyto metametody definují s tečkou a dvěma parametry: obě strany jsou si rovné. (function Pytel:__lt(jiny), se self vlevo a jiny vpravo, by byla tatáž funkce.)
__addje+.brambory + dalsiBramboryzavoláPytel.__add(brambory, dalsiBrambory)a ta vrátí nový pytel s 35 kg; žádný z obou pytlů se nezmění. Stejně fungují__subpro-,__mulpro*a__divpro/.__eqje==(a také~=, jeho opak). Tady jsou dva pytle stejné, když je v nich stejná plodina a stejně váží, i když jsou to dvě různé tabulky. Lua zavolá__eq, jen když jsou na obou stranách tabulky; pytel porovnaný s číslem prostě stejný není.__ltje<(z anglického less than, menší než).a > bje totéž cob < a, a tak i>používá__lt.<=a>=potřebují vlastní metametodu__le; bez ní skončí chybouattempt to compare two table values.table.sortporovnává prvky pomocí<. Díky__ltproto seřadí pytle i bez porovnávací funkce, od nejlehčího. Bez__ltbytable.sort(pytle)skončilo chybouattempt to compare two table values, tentokrát bezmain.lua:a čísla řádku na začátku, protože chyba vznikne uvnitřtable.sort. Řádek, který ji zavolal, najdete ve výpisu pod hláškou.
Typická chyba je použít operátor s něčím, co objekt není. brambory + 5 zavolá Pytel.__add(brambory, 5) a b.kg u čísla 5 skončí chybou attempt to index a number value (local 'b').
Jak psát:
Pokyny
Spusťte program: table.sort neumí plodiny porovnat. Přidejte třídě Plodina metametodu __lt, aby levnější plodina byla první. Program vypíše:
Mrkev: 5 mincí
Brambory: 8 mincí
Jahody: 12 mincí
Dýně: 20 mincíPřidejte __eq: dvě plodiny jsou stejné, když mají stejný název i stejnou cenu. Na konci programu vypište, jestli se plodiny[1] rovná nové plodině Plodina.new("Mrkev", 5), a na další řádek, jestli se plodiny[2] rovná Plodina.new("Brambory", 10):
true
falseHugo prodává plodiny i v balíčcích. Přidejte __add, která ze dvou plodin vyrobí novou: její název budou oba názvy spojené textem + a její cena bude součet obou cen. Na konci vypište plodiny[1] + plodiny[2] a potom plodiny[1] + plodiny[2] + plodiny[3]. Druhé sčítání funguje, protože plodiny[1] + plodiny[2] je zase plodina:
Mrkev + Brambory: 13 mincí
Mrkev + Brambory + Jahody: 25 mincíZačněte programovat zdarma
7/9