Форматирование строк
Часть раздела Object Oriented Programming путешествия по Lua на Coddy — урок 16 из 70.
Когда вы выводите объект напрямую, Lua показывает нечто малополезное, вроде table: 0x55a... — просто адрес в памяти. Метаметод __tostring позволяет вам точно определить, какая строка будет представлять ваш объект при его выводе на печать или преобразовании в текст.
В паттерне классов вы добавляете __tostring как функцию в таблицу вашего класса. Поскольку сам класс служит метатаблицей для экземпляров, Lua автоматически находит и использует эту функцию:
local Player = {}
Player.__index = Player
function Player:new(name, level)
local instance = {}
setmetatable(instance, self)
instance.name = name
instance.level = level
return instance
end
function Player:__tostring()
return "Player: " .. self.name .. " (Level " .. self.level .. ")"
endТеперь, когда вы выводите экземпляр Player, Lua автоматически вызывает ваш метод __tostring:
local hero = Player:new("Luna", 5)
print(hero) -- Вывод: Player: Luna (Level 5)Обратите внимание, что __tostring использует синтаксис с двоеточием и получает self, предоставляя вам доступ ко всем данным экземпляра. Функция должна возвращать строку — вы можете отформатировать её так, как это удобно для вашего объекта, объединяя любые атрибуты в читаемое представление.
Задание
ЛегкоДавайте создадим класс Book, который умеет представлять себя! Когда вы напрямую выводите объект книги на печать, Lua будет отображать красиво отформатированную строку вместо непонятного адреса памяти — и все это благодаря метаметоду __tostring.
Вы организуете свой код в двух файлах:
Book.lua: Определите классBook, используя стандартный паттерн прототипа. Каждая книга должна хранитьtitleиauthor. Добавьте конструктор:new(title, author)и реализуйте метаметод__tostring, чтобы при выводе книги на печать ее информация отображалась в читаемом формате.main.lua: Подключите модуль Book, создайте экземпляры книг и выведите их напрямую, чтобы увидеть ваше пользовательское форматирование строк в действии.
Ваш метод __tostring должен возвращать строку именно в таком формате:
"[title]" by [author]Обратите внимание, что название (title) в выходной строке заключено в двойные кавычки.
Вы получите четыре входных значения:
- Название первой книги
- Автор первой книги
- Название второй книги
- Автор второй книги
В основном файле создайте две книги, используя предоставленные входные данные, и выведите каждую книгу напрямую (не вызывая метод, а просто через print(book)). Каждая книга должна быть выведена на отдельной строке.
Например, если входные данные — The Hobbit, J.R.R. Tolkien, 1984 и George Orwell, вывод должен быть следующим:
"The Hobbit" by J.R.R. Tolkien
"1984" by George OrwellПомните, что __tostring должен возвращать строку, и так как таблица вашего класса служит метатаблицей для экземпляров, Lua автоматически найдет и использует вашу функцию __tostring при выводе книги на печать.
Шпаргалка
Метаметод __tostring определяет, как объект представляется в виде строки при выводе на печать или преобразовании в текст.
Без __tostring при выводе объекта на печать отображается только его адрес в памяти:
print(someObject) -- Вывод: table: 0x55a...Добавьте __tostring как метод в ваш класс, чтобы настроить строковое представление:
local Player = {}
Player.__index = Player
function Player:new(name, level)
local instance = {}
setmetatable(instance, self)
instance.name = name
instance.level = level
return instance
end
function Player:__tostring()
return "Player: " .. self.name .. " (Level " .. self.level .. ")"
endКогда вы выводите экземпляр на печать, Lua автоматически вызывает __tostring:
local hero = Player:new("Luna", 5)
print(hero) -- Вывод: Player: Luna (Level 5)Ключевые моменты:
- Используйте синтаксис с двоеточием (
:), чтобы метод получалself - Метод должен возвращать строку
- Доступ к данным экземпляра осуществляется через
self - Поскольку таблица класса служит метатаблицей, Lua находит
__tostringавтоматически
Попробуйте сами
-- Подключить модуль Book
local Book = require('Book')
-- Считать входные данные
local title1 = io.read()
local author1 = io.read()
local title2 = io.read()
local author2 = io.read()
-- TODO: Создать два экземпляра книги, используя Book:new()
-- TODO: Вывести каждую книгу напрямую (просто используйте print(book))
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Концепция 'self'
Таблицы с функциямиЯвный 'self'Синтаксис с двоеточиемТочка против двоеточияИтоги — Движущаяся точка4Проект: Цифровой банк
Настройка проектаМетод пополнения7Полиморфизм и переопределение
Переопределение методовВызов родительских методовУтиная типизацияОбщий интерфейсПроверка типаИтоги — Роли сотрудников2Паттерн прототипа класса
Концепция прототипаСвязывание через __indexКонструктор :new()Инициализация атрибутовНезависимые экземплярыИтоги — Автозавод5Перегрузка операторов в ООП
Сложение объектовВычитание объектовКонкатенация объектовСравнение объектов (<, >)Повторение — Математика кошелька8Инкапсуляция
Соглашения об именованииЗамыкания для приватностиДоступ через замыканияТаблицы только для чтенияЛогика валидацииИтоги — Защищенное хранилище11Паттерны проектирования (Lite)
Фабричные функцииТаблица SingletonПаттерн IteratorObserver (Слушатель)Итоги — Logger Factory3Состояние и поведение объектов
Переменные экземпляраГеттерыСеттерыВычисляемые свойстваФорматирование строкПроверка на равенствоПовторение — Оценка студента6Основы наследования
Настройка наследованияНаследование методовРасширение конструктораДобавление дочерних методовОбщее и уникальноеИтоги: Иерархия фигур