Menu
Coddy logo textTech

Переопределение методов

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

До сих пор дочерние классы наследовали методы родительских классов и добавляли новые. Но что, если дочернему классу нужно то же имя метода, но с другим поведением? Это называется переопределением метода.

Когда вы определяете method в child class с тем же именем, что и у method в parent class, версия child получает приоритет. Цепочка поиска Lua сначала проверяет child class; если находит там method, прекращает поиск.

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 переопределяет speak()
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()
    print(self.name .. " barks: Woof!")
end

Теперь каждый class по-разному реагирует на один и тот же вызов method:

local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")

generic:speak()  -- Вывод: Creature издаёт звук
buddy:speak()    -- Вывод: Buddy лает: Woof!

Dog полностью заменяет версию родителя для экземпляров Dog. Это позволяет создавать специализированное поведение, сохраняя единый интерфейс: каждое животное может использовать :speak(), но каждый вид делает это по-своему.

challenge icon

Задание

Легко

Давайте создадим небольшое животное царство, где разные существа говорят по-своему! Вы создадите родительский класс Animal и два дочерних класса, Cat и Cow, каждый из которых переопределит метод :speak() родительского класса, реализовав собственное специализированное поведение.

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

  • Animal.lua: Ваш базовый класс с конструктором :new(name), который сохраняет имя животного. Добавьте метод :speak(), выводящий имя животного, за которым следует makes a sound. Это поведение по умолчанию, которое дочерние классы переопределят.
  • Cat.lua: Дочерний класс, который наследуется от Animal. Его конструктор :new(name) должен вызвать конструктор родительского класса, а затем повторно связать метатаблицу с Cat. Переопределите метод :speak(), чтобы cats говорили иначе: выведите имя cat, за которым следует meows: Meow!
  • Cow.lua: Ещё один дочерний класс, наследующийся от Animal. Настройте конструктор так же, как в Cat. Переопределите :speak(), чтобы cows выводили своё имя, за которым следует moos: Moo!
  • main.lua: Объедините всё вместе! Считайте два имени из input, создайте Cat с первым именем и Cow со вторым именем, затем вызовите у каждого :speak(), чтобы продемонстрировать, что одно и то же имя метода даёт разный вывод в зависимости от класса.

Вы получите два входных значения:

  1. Имя cat
  2. Имя cow

В основном файле создайте обоих животных и сначала вызовите :speak() у cat, а затем у cow.

Например, если входные значения — Whiskers и Bessie, вывод должен быть таким:

Whiskers meows: Meow!
Bessie moos: Moo!

Обратите внимание: оба животных реагируют на один и тот же вызов метода :speak(), но каждый выдаёт вывод, характерный для его типа. Версия Cat полностью заменяет общее поведение родительского класса "makes a sound", и Cow делает то же самое. Это переопределение метода в действии: один интерфейс, разные реализации!

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

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

local Cat = require('Cat')
local Cow = require('Cow')

-- Прочитай ввод
local catName = io.read()
local cowName = io.read()

-- TODO: Создай Cat с первым именем

-- TODO: Создай Cow со вторым именем

-- TODO: Вызови :speak() сначала у кота, затем у коровы
quiz iconПроверьте себя

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

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

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