Menu
Coddy logo textTech

Вызов родительских методов

Часть раздела Объектно-ориентированное программирование путешествия по Lua на Coddy. Урок 38 из 70.

Иногда полностью переопределять method — не то, что вам нужно. Вместо этого вы можете extends поведение parent: выполнить то, что делает parent, а затем добавить что-то ещё. Для этого можно напрямую вызвать parent method из переопределения child.

В этой технике используется точечный синтаксис с именем родительского класса, при этом self явно передаётся как первый аргумент:

local Animal = {}
Animal.__index = Animal

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

function Animal:speak()
    print(self.name .. " makes a sound")
end

-- Dog расширяет поведение родителя
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = Animal.new(Animal, name)
    setmetatable(obj, Dog)
    return obj
end

function Dog:speak()
    Animal.speak(self)  -- Сначала вызвать метод родителя
    print(self.name .. " wags tail happily")
end

Ключевая строка — Animal.speak(self). Используя точечный синтаксис родительского класса и передавая self вручную, мы вызываем исходный метод, прежде чем добавить собственное поведение:

local buddy = Dog:new("Buddy")
buddy:speak()
-- Вывод:
-- Buddy издаёт звук
-- Buddy радостно виляет хвостом

Этот шаблон полезен, когда parent method выполняет важную работу, которую вы не хотите дублировать. child может сначала, в конце или даже в середине своего кода выполнить логику parent, что даёт вам полный контроль над тем, как сочетаются разные варианты поведения.

challenge icon

Задание

Легко

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

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

  • Person.lua: ваш базовый class с конструктором :new(name), который сохраняет имя person. Добавьте метод :introduce(), который выводит имя person, за которым следует says hi. Это базовое поведение, которое будет расширено.
  • FormalPerson.lua: дочерний class, который наследуется от Person. Его constructor должен вызвать parent constructor для обработки имени. Переопределите метод :introduce(), но вместо полной замены поведения parent сначала вызовите метод parent с помощью Person.introduce(self), а затем выведите дополнительную строку с именем person, за которым следует bows politely.
  • main.lua: подключите свой модуль FormalPerson, считайте имя из input, создайте instance FormalPerson и вызовите :introduce(), чтобы увидеть оба поведения вместе.

Вы получите один input: имя person.

Когда вы вызовете :introduce() у FormalPerson, он должен вывести две строки: первую — из метода parent, вторую — из дополнения child:

{name} says hi
{name} bows politely

Например, если input — Eleanor, результатом должен быть:

Eleanor says hi
Eleanor bows politely

Ключевая идея заключается в том, что FormalPerson не дублирует логику "says hi". Он делегирует эту работу методу parent, а затем добавляет собственное уникальное поведение. Это сохраняет чистоту кода и демонстрирует, как child classes могут расширять, а не заменять функциональность parent!

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

-- main.lua: Точка входа для системы приветствий

local FormalPerson = require('FormalPerson')

-- Считать имя человека из ввода
local name = io.read()

-- TODO: Создать экземпляр FormalPerson с заданным именем

-- TODO: Вызвать метод introduce у экземпляра FormalPerson
quiz iconПроверьте себя

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

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

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