Метаметод __index
Часть раздела Логика и управление потоком путешествия по Lua на Coddy. Урок 18 из 54.
Теперь, когда ты знаешь, как прикреплять метатаблицы к таблицам, пришло время узнать о самом важном метаметоде: __index. Этот метаметод определяет, что происходит, когда ты пытаешься получить доступ к ключу, которого нет в таблице.
Обычно, когда вы ищете ключ, которого нет в таблице, Lua возвращает nil. Но если у таблицы есть метатаблица с полем __index, Lua проверит это поле. Если __index указывает на другую таблицу, Lua будет искать ключ там:
local defaults = {
health = 100,
speed = 10
}
local player = {name = "Alice"}
local meta = {__index = defaults}
setmetatable(player, meta)
print(player.name) -- Вывод: Alice
print(player.health) -- Вывод: 100В этом примере у player есть только ключ name. Когда вы обращаетесь к player.health, Lua не находит его в player, поэтому проверяет поле __index метатаблицы. Поскольку __index указывает на таблицу defaults, Lua ищет там и находит health = 100.
Это создает механизм резервных значений, при котором одна таблица может предоставлять значения по умолчанию для другой. Исходная таблица сохраняет собственные значения, но любые отсутствующие ключи автоматически ищутся в резервной таблице.
__index также может быть функцией. Если ключ отсутствует, Lua вызывает её, передавая таблицу и ключ, и использует возвращённое ею значение:
local scores = {alice = 12}
setmetatable(scores, {
__index = function(t, key)
return 0 -- каждое отсутствующее имя считается равным 0
end
})
print(scores.alice) -- Вывод: 12
print(scores.bob) -- Вывод: 0Таблица задаёт фиксированные значения по умолчанию; функция может вычислить значение для любого отсутствующего ключа.
Задание
ЛегкоНапиши функцию createCharacterWithDefaults, которая принимает name и level и возвращает таблицу персонажа со значениями характеристик по умолчанию.
Создай таблицу персонажа с указанными именем и уровнем. Используй метатаблицу с __index, чтобы задавать значения по умолчанию для всех отсутствующих характеристик (здоровье, мана, сила).
Логика:
- Создай таблицу defaults с ключами:
health = 100,mana = 50,strength = 10 - Создай таблицу персонажа с ключами:
name(указанное имя) иlevel(указанный уровень) - Создай метатаблицу с
__index, указывающим на таблицу defaults - Присоедини метатаблицу к таблице персонажа с помощью
setmetatable() - Верни таблицу персонажа
Параметры:
name(строка): имя персонажаlevel(число): уровень персонажа
Возвращает: таблицу персонажа с именем, уровнем и характеристиками по умолчанию, доступными через метатаблицу (таблица)
Попробуйте сами
function createCharacterWithDefaults(name, level)
-- Напишите код здесь
end
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Продвинутая итерация таблиц
Итерация с помощью pairs()Итерация с помощью ipairs()pairs() против ipairs()Повторение — Лист персонажа2Дополнительные функции библиотеки table
table.concat()Создание таблиц и unpack()table.sort()Пользовательская сортировка с помощью функцийИтоги — Таблица рекордовПотренируйтесь самостоятельно: Онлайн-компилятор Lua