Menu
Coddy logo textTech

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

Часть раздела Object Oriented Programming путешествия по Lua на Coddy — урок 31 из 70.

До сих пор вы создавали классы, в которых каждый объект ищет методы в одной таблице прототипов. Но что, если вы хотите, чтобы один класс основывался на другом? Здесь на помощь приходит наследование — дочерний класс может получать доступ ко всему из родительского класса, добавляя при этом свои собственные функции.

Ключевая идея заключается в том, что сама таблица класса может иметь метатаблицу. Когда Lua не может найти что-то в дочернем классе, она ищет это в __index метатаблицы дочернего класса — которая указывает на родительский класс.

-- Родительский класс
local Animal = {}
Animal.__index = Animal

function Animal:new()
    local obj = {}
    setmetatable(obj, Animal)
    return obj
end

function Animal:breathe()
    print("Breathing...")
end

Теперь вот настройка наследования. Мы создаем дочерний класс и устанавливаем его метатаблицу так, чтобы она обращалась к родительскому:

-- Дочерний класс
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

Эта единственная строка — setmetatable(Dog, {__index = Animal}) — создает связь наследования. Когда экземпляр Dog вызывает метод, не найденный в Dog, Lua проверяет Animal.

Цепочка поиска работает следующим образом: instance → Dog → Animal. На каждом этапе используется __index для поиска следующей таблицы. Это позволяет дочерним классам автоматически наследовать все методы родителя без их копирования.

challenge icon

Задание

Легко

Давайте построим вашу первую иерархию наследования! Вы создадите простую связь между родительским и дочерним классами, где класс Machine служит базовым, а класс Robot наследуется от него.

Вы организуете свой код в трех файлах:

  • Machine.lua: Определите родительский класс, используя стандартный паттерн классов. Включите конструктор :new() и метод :status(), который выводит Machine is operational. Не забудьте настроить __index и вернуть класс в конце файла.
  • Robot.lua: Определите дочерний класс, который наследуется от Machine. Подключите модуль Machine, настройте таблицу Robot с ее собственным __index и установите связь наследования с помощью setmetatable(Robot, {__index = Machine}). Включите конструктор :new(), который создает экземпляр с Robot в качестве метатаблицы.
  • main.lua: Соберите все вместе, подключив модуль Robot, создав экземпляр Robot и вызвав унаследованный метод :status().

Ключевая концепция здесь заключается в том, что класс Robot сам не определяет :status() — он наследует этот метод от Machine через цепочку метатаблиц. Когда вы вызываете :status() у экземпляра Robot, Lua сначала ищет его в Robot, не находит, а затем переходит по ссылке __index к Machine, где и обнаруживает метод.

Ваш вывод должен быть:

Machine is operational

Эта единственная строка доказывает, что наследование работает — ваш Robot успешно получил доступ к методу, определенному только в его родительском классе!

Шпаргалка

Чтобы создать наследование в Lua, установите метатаблицу таблицы класса так, чтобы она указывала на родительский класс с помощью __index:

-- Родительский класс
local Animal = {}
Animal.__index = Animal

function Animal:new()
    local obj = {}
    setmetatable(obj, Animal)
    return obj
end

function Animal:breathe()
    print("Breathing...")
end

-- Дочерний класс
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

Связь наследования создается с помощью setmetatable(Dog, {__index = Animal}). Это позволяет экземплярам Dog автоматически получать доступ к методам Animal.

Цепочка поиска выглядит следующим образом: экземпляр → Дочерний класс → Родительский класс. На каждом этапе используется __index для поиска следующей таблицы.

Попробуйте сами

-- main.lua: Собираем всё вместе

-- TODO: Подключите модуль Robot

-- TODO: Создайте экземпляр Robot, используя Robot:new()

-- TODO: Вызовите унаследованный метод :status() для вашего экземпляра робота
-- Это должно вывести "Machine is operational"
quiz iconПроверьте себя

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

Все уроки раздела Object Oriented Programming