Menu
Coddy logo textTech

Настройка наследования

Часть раздела Объектно-ориентированное программирование путешествия по 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, чтобы найти следующую таблицу для поиска. Это позволяет дочерним классам автоматически наследовать все методы родительского класса, не копируя их.

challenge icon

Задание

Легко

Давайте создадим вашу первую иерархию 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"
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Lua