Printing Objects
When you print an object, print(carrot), Lua doesn't know what's important about it. It prints table: and the table's address in the computer's memory, something like table: 0x109010, which doesn't tell you much. The metamethod __tostring fixes that. It's a function that gets the object and returns a text, and print and tostring use that text:
local Crop = {}
Crop.__index = Crop
function Crop.new(name, days)
local crop = {name = name, days = days, age = 0}
setmetatable(crop, Crop)
return crop
end
function Crop:grow()
self.age = self.age + 1
end
function Crop:__tostring()
if self.age >= self.days then
return self.name .. " (ready)"
end
return self.name .. " (day " .. self.age .. " of " .. self.days .. ")"
end
local field = {Crop.new("Wheat", 2), Crop.new("Carrot", 3), Crop.new("Pumpkin", 7)}
for day = 1, 2 do
for _, crop in ipairs(field) do
crop:grow()
end
end
for _, crop in ipairs(field) do
print(crop)
end
print("First in the field: " .. tostring(field[1]))This prints:
Wheat (ready)
Carrot (day 2 of 3)
Pumpkin (day 2 of 7)
First in the field: Wheat (ready)Crop is the metatable of every crop, so one __tostring in Crop works for all of them. You write it like any other method, and self is the crop it should describe: function Crop:__tostring() means Crop.__tostring = function(self). Inside, it can do anything a method can, such as check whether the crop is ready. Lua calls it for you whenever it needs the object as a text: in print, in tostring, and for %s in string.format, so string.format("%s!", field[1]) gives Wheat (ready)!.
Typical mistakes:
- Joining with
... The operator..doesn't use__tostring. Ifcarrotis a crop,"In the field: " .. carrotends withattempt to concatenate a table value (local 'carrot'). Turn the object into a text first withtostring(carrot), as in the last line of the example. - Printing instead of returning.
__tostringmust give the text back withreturn. If it prints the text and returns nothing, the program ends with the error'__tostring' must return a string.
Instructions
Run the program: it prints the hen as table: and an address. Add the metamethod __tostring to Hen, so that print(goldie) prints:
Goldie (2 eggs)Below it, print the line Best hen: Goldie (2 eggs). Build it with .. from the hen itself, goldie, not from a text you write out.
Goldie (2 eggs)
Best hen: Goldie (2 eggs)Pearl has laid just one egg, and Pearl (1 eggs) would be wrong. Change __tostring so that it writes egg when the hen has exactly 1 egg. Create Pearl with Hen.new, let her lay 1 egg, and print her below the other lines:
Goldie (2 eggs)
Best hen: Goldie (2 eggs)
Pearl (1 egg)Start programming for free
6/9