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. If carrot is a crop, "In the field: " .. carrot ends with attempt to concatenate a table value (local 'carrot'). Turn the object into a text first with tostring(carrot), as in the last line of the example.
  • Printing instead of returning. __tostring must give the text back with return. 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

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

6/9