Настройка наследования
Часть раздела Объектно-ориентированное программирование путешествия по Lua на Coddy. Урок 31 из 70.
До сих пор ты создавал классы, в которых каждый объект ищет методы в одной таблице прототипа. Но что, если ты хочешь, чтобы один класс строился на основе другого? Здесь и появляется inheritance: дочерний класс может получать доступ ко всему из родительского класса, добавляя при этом собственные возможности.
Ключевая идея заключается в том, что сама таблица класса может иметь метатаблицу. Когда Lua не может найти что-либо в дочернем классе, он ищет это в __index метатаблицы дочернего класса, которая указывает на родительский класс.
-- Родительский класс
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
endТеперь рассмотрим настройку inheritance. Мы создаём дочерний класс и устанавливаем его metatable так, чтобы он обращался к Parent:
-- Дочерний класс
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})Эта единственная строка, setmetatable(Dog, {__index = Animal}), создаёт link inheritance. Когда instance Dog вызывает method, не найденный в Dog, Lua проверяет Animal.
Цепочка поиска работает так: instance → Dog → Animal. На каждом шаге используется __index, чтобы найти следующую таблицу для поиска. Это позволяет дочерним классам автоматически наследовать все методы родительского класса, не копируя их.
Задание
ЛегкоДавайте создадим вашу первую иерархию inheritance! Вы создадите простую связь между родительским и дочерним классами, где класс Machine служит базовым, а класс Robot inherits от него.
Вы организуете код в трёх файлах:
Machine.lua: определите свой родительский класс по стандартному шаблону класса. Добавьте конструктор:new()и метод:status(), который выводитMachine is operational. Не забудьте настроить__indexи вернуть класс в конце файла.Robot.lua: определите свой дочерний класс, который inherits от Machine. Подключите модуль Machine, настройте таблицу Robot с её собственным__indexи установите связь inheritance с помощьюsetmetatable(Robot, {__index = Machine}). Добавьте конструктор:new(), который создаёт instance с Robot в качестве его metatable.main.lua: объедините всё вместе, подключив свой модуль Robot, создав instance Robot и вызвав унаследованный метод:status().
Ключевая концепция здесь заключается в том, что ваш класс Robot сам не определяет :status(). Он inherits этот метод от Machine через цепочку metatable. Когда вы вызываете :status() у instance Robot, lua сначала выполняет поиск в Robot, не находит его, а затем следует по ссылке __index к Machine, где обнаруживает этот метод.
Результат должен быть таким:
Machine is operationalЭта единственная строка доказывает, что inheritance работает. Ваш Robot успешно получил доступ к методу, определённому только в его родительском классе!
Попробуйте сами
-- main.lua: Собери всё вместе
-- TODO: Подключи модуль Robot
-- TODO: Создай экземпляр Robot с помощью Robot:new()
-- TODO: Вызови унаследованный метод :status() на своём экземпляре робота
-- This should print "Machine is operational"
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Концепция 'self'
Таблицы с функциямиЯвный 'self'Синтаксис с двоеточиемТочка против двоеточияИтоги — Движущаяся точка4Проект: Цифровой банк
Настройка проектаМетод пополнения7Полиморфизм и переопределение
Переопределение методовВызов родительских методовУтиная типизацияОбщий интерфейсПроверка типаИтоги — Роли сотрудников2Паттерн прототипа класса
Концепция прототипаСвязывание через __indexКонструктор :new()Инициализация атрибутовНезависимые экземплярыИтоги — Автозавод5Перегрузка операторов в ООП
Сложение объектовВычитание объектовКонкатенация объектовСравнение объектов (<, >)Повторение — Математика кошелька8Инкапсуляция
Соглашения об именованииЗамыкания для приватностиДоступ через замыканияТаблицы только для чтенияЛогика валидацииИтоги — Защищенное хранилище11Паттерны проектирования (Lite)
Фабричные функцииТаблица SingletonПаттерн IteratorObserver (Слушатель)Итоги — Logger Factory3Состояние и поведение объектов
Переменные экземпляраГеттерыСеттерыВычисляемые свойстваФорматирование строкПроверка на равенствоПовторение — Оценка студента6Основы наследования
Настройка наследованияНаследование методовРасширение конструктораДобавление дочерних методовОбщее и уникальноеИтоги: Иерархия фигурПотренируйтесь самостоятельно: Онлайн-компилятор Lua