Вывод объектов
Когда вы выводите объект, print(carrot), Lua не знает, что в нём важно. Он выводит table: и адрес таблицы в памяти компьютера, что-то вроде table: 0x109010, и это мало о чём говорит. Исправляет это метаметод __tostring. Это функция, которая получает объект и возвращает строку, а print и tostring используют эту строку:
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 .. " (созрела)"
end
return self.name .. " (день " .. self.age .. " из " .. self.days .. ")"
end
local field = {Crop.new("Пшеница", 2), Crop.new("Морковь", 3), Crop.new("Тыква", 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("Первая на поле: " .. tostring(field[1]))Он выводит:
Пшеница (созрела)
Морковь (день 2 из 3)
Тыква (день 2 из 7)
Первая на поле: Пшеница (созрела)Crop — метатаблица каждой культуры, поэтому один __tostring в Crop работает для всех. Вы пишете его как любой другой метод, а self — это культура, которую нужно описать: function Crop:__tostring() означает Crop.__tostring = function(self). Внутри можно делать всё, что делает метод, например проверить, созрела ли культура. Lua вызывает его сам, когда ему нужен объект в виде строки: в print, в tostring и для %s в string.format, поэтому string.format("%s!", field[1]) даёт Пшеница (созрела)!.
Типичные ошибки:
- Склеивание через
... Оператор..не использует__tostring. Еслиcarrot— культура, то"На поле: " .. carrotзавершится с ошибкойattempt to concatenate a table value (local 'carrot'). Сначала превратите объект в строку черезtostring(carrot), как в последней строке примера. - Вывод вместо возврата.
__tostringдолжен отдавать строку черезreturn. Если он выводит строку и ничего не возвращает, программа завершится с ошибкой'__tostring' must return a string.
Задание
- 1
Запустите программу: она выводит курицу как
table:и адрес. Добавьте вHenметаметод__tostring, чтобыprint(goldie)выводил:Златка (яиц: 2) - 2
Ниже выведите строку
Лучшая курица: Златка (яиц: 2). Соберите её через..из самой курицы,goldie, а не из строки, которую вы пишете вручную.Златка (яиц: 2) Лучшая курица: Златка (яиц: 2) - 3
Перла пока ничего не снесла, и
Перла (яиц: 0)выглядит странно. Измените__tostringтак, чтобы у курицы без яиц он писал(яиц пока нет). Создайте Перлу черезHen.new, не давая ей нестись, и выведите её под остальными строками:Златка (яиц: 2) Лучшая курица: Златка (яиц: 2) Перла (яиц пока нет)