Menu
Coddy logo textTech

Добавление дочерних методов

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

Наследование позволяет дочерним классам получать доступ к родительским методам, но настоящая мощь заключается в добавлении новых методов, которыми обладает только дочерний класс. Dog может делать всё то же самое, что и Animal, плюс вещи, уникальные для собак — например, лаять.

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

local Animal = {}
Animal.__index = Animal

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

function Animal:breathe()
    print(self.name .. " is breathing")
end

-- Dog наследует от Animal
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

-- Новый метод только в Dog
function Dog:bark()
    print(self.name .. " says: Woof!")
end

Теперь экземпляры Dog могут использовать как унаследованные, так и уникальные методы:

local buddy = Dog:new("Buddy")
buddy:breathe()  -- Вывод: Buddy is breathing (унаследовано)
buddy:bark()     -- Вывод: Buddy says: Woof! (только для дочернего класса)

Родительский класс остается неизменным — вызов :bark() для обычного Animal приведет к ошибке, так как этот метод там не существует. Именно так наследование позволяет специализировать поведение, сохраняя общую функциональность в одном месте.

challenge icon

Задание

Легко

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

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

  • Pet.lua: Определите родительский класс с конструктором :new(name), который сохраняет имя питомца. Включите метод :greet(), который выводит имя питомца, за которым следует says hello. Настройте стандартный паттерн класса и верните класс.
  • Cat.lua: Определите дочерний класс, который наследуется от Pet. Конструктор :new(name) вашего Cat должен вызывать родительский конструктор для инициализации имени, а затем повторно привязывать метатаблицу к Cat. Добавьте специфичный для дочернего класса метод :purr(), который выводит имя кошки, за которым следует purrs contentedly. Этот метод существует только в Cat — у Pet его нет!
  • main.lua: Подключите модуль Cat, считайте имя из входных данных, создайте экземпляр Cat и продемонстрируйте, что он может использовать как унаследованный метод :greet(), так и свой собственный уникальный метод :purr().

Вы получите одни входные данные: имя кошки.

В вашем основном файле создайте объект Cat с заданным именем, затем вызовите :greet(), а после него :purr() на отдельных строках.

Например, если на вход подается Whiskers, вывод должен быть следующим:

Whiskers says hello
Whiskers purrs contentedly

Первая строка выводится унаследованным методом :greet(), определенным в Pet, а вторая строка — методом :purr(), который существует только в Cat. Это демонстрирует, как дочерние классы могут делать все то же самое, что и их родители, плюс свои собственные специализированные действия!

Шпаргалка

Дочерние классы могут добавлять новые методы, которыми обладают только они, при этом наследуя все родительские методы. Экземпляры сначала ищут методы в своем собственном классе, а затем обращаются к родительскому.

Чтобы добавить метод, специфичный для дочернего класса, определите его в таблице дочернего класса:

local Animal = {}
Animal.__index = Animal

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

function Animal:breathe()
    print(self.name .. " is breathing")
end

-- Dog наследует от Animal
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:bark()
    print(self.name .. " says: Woof!")
end

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

local buddy = Dog:new("Buddy")
buddy:breathe()  -- Унаследовано от Animal
buddy:bark()     -- Метод только для дочернего класса

Родительский класс остается неизменным — у него нет доступа к методам, специфичным для дочернего класса.

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

-- main.lua: Создание объекта Cat и демонстрация наследования

local Cat = require('Cat')

-- Чтение имени кошки из ввода
local name = io.read()

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

-- TODO: Вызвать унаследованный метод :greet() (от Pet)

-- TODO: Вызвать специфичный для Cat метод :purr()
quiz iconПроверьте себя

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

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