Menu
Coddy logo textTech

Общее и уникальное

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

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

Рассмотрим следующую иерархию:

local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia"  -- Общее: определено в классе

function Animal:new(name)
    local obj = {name = name}  -- Уникальное: хранится в каждом экземпляре
    setmetatable(obj, Animal)
    return obj
end
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark"  -- Общий для всех собак

function Dog:new(name, breed)
    local obj = Animal.new(Animal, name)
    obj.breed = breed  -- Уникально: у каждой собаки своя порода
    setmetatable(obj, Dog)
    return obj
end

Когда вы создаете экземпляр Dog, некоторые значения существуют непосредственно в объекте, в то время как другие находятся через цепочку поиска:

local rex = Dog:new("Rex", "German Shepherd")

-- Уникально для этого экземпляра (хранится в rex)
print(rex.name)    -- "Rex"
print(rex.breed)   -- "German Shepherd"
-- Общие (найдены через поиск)
print(rex.sound)   -- "bark" (от Dog)
print(rex.kingdom) -- "Animalia" (от Animal)

Ключевое отличие: поля, присвоенные obj в конструкторах, уникальны для каждого экземпляра, в то время как поля, определенные непосредственно в таблицах классов, являются общими для всех экземпляров этого класса и его наследников.

challenge icon

Задание

Легко

Давайте изучим, как данные передаются через иерархию наследования, создав систему классов Creature и Dragon. Вы воочию увидите, какие атрибуты являются общими для всех экземпляров, а какие — уникальными для каждого отдельного объекта.

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

  • Creature.lua: Определите родительский класс с общим атрибутом уровня класса world = "Fantasy Realm", который разделяют все существа. Включите конструктор :new(name), который сохраняет имя существа как атрибут экземпляра.
  • Dragon.lua: Определите дочерний класс, который наследуется от Creature. Добавьте общий атрибут уровня класса element = "fire", который разделяют все драконы. Ваш конструктор :new(name, color) должен вызывать родительский конструктор для имени, а затем добавлять color как уникальный атрибут экземпляра для каждого дракона.
  • main.lua: Создайте двух разных драконов и проверьте их атрибуты, чтобы продемонстрировать разницу между общими и уникальными данными.

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

  1. Имя и цвет первого дракона, разделенные запятой (например, Smaug,red)
  2. Имя и цвет второго дракона, разделенные запятой (например, Draco,gold)

В вашем основном файле создайте обоих драконов с их соответствующими именами и цветами. Затем выведите следующую информацию в строгом порядке:

  1. name первого дракона
  2. color первого дракона
  3. name второго дракона
  4. color второго дракона
  5. element первого дракона (общий из класса Dragon)
  6. element второго дракона (общий из класса Dragon)
  7. world первого дракона (общий из класса Creature)

Например, если входные данные — Smaug,red и Draco,gold, вывод должен быть следующим:

Smaug
red
Draco
gold
fire
fire
Fantasy Realm

Обратите внимание, что name и color у каждого дракона разные (уникальные атрибуты экземпляра), в то время как element и world одинаковы для обоих (общие атрибуты класса, найденные через цепочку поиска).

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

-- main.lua: Создание драконов и демонстрация общих и уникальных атрибутов

local Dragon = require('Dragon')

-- Чтение ввода для первого дракона (имя,цвет)
local input1 = io.read()
-- Чтение ввода для второго дракона (имя,цвет)
local input2 = io.read()

-- TODO: Разобрать первый ввод, чтобы извлечь имя и цвет
-- Подсказка: Используйте string.match с шаблоном "([^,]+),([^,]+)"

-- TODO: Разобрать второй ввод, чтобы извлечь имя и цвет

-- TODO: Создать первого дракона с его именем и цветом

-- TODO: Создать второго дракона с его именем и цветом

-- TODO: Вывести следующее по порядку:
-- 1. Имя первого дракона
-- 2. Цвет первого дракона
-- 3. Имя второго дракона
-- 4. Цвет второго дракона
-- 5. Элемент первого дракона (общий из класса Dragon)
-- 6. Элемент второго дракона (общий из класса Dragon)
-- 7. Мир первого дракона (общий из класса Creature)
quiz iconПроверьте себя

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

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