Вычисляемые свойства
Часть раздела Объектно-ориентированное программирование путешествия по Lua на Coddy. Урок 15 из 70.
Геттеры и сеттеры обеспечивают доступ к сохранённым значениям, но иногда вам нужны данные, которые не существуют в виде сохранённого поля. Их необходимо вычислить на основе других атрибутов. Они называются вычисляемыми свойствами.
Рассмотрим прямоугольник. Вы храните его width и height, но area нигде не хранится: она вычисляется путём перемножения этих двух значений. Вместо хранения избыточных данных вы создаёте метод, который вычисляет и возвращает результат:
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = {}
setmetatable(instance, self)
instance.width = width
instance.height = height
return instance
end
function Rectangle:getArea()
return self.width * self.height
endМетод :getArea() не возвращает сохранённое значение. Он вычисляет площадь заново при каждом вызове. У этого подхода есть важное преимущество: если ширина или высота изменится, площадь автоматически отразит новые размеры, и вам не потребуется ничего обновлять.
local box = Rectangle:new(5, 3)
print(box:getArea()) -- Вывод: 15
box.width = 10
print(box:getArea()) -- Вывод: 30Вычисляемые свойства поддерживают согласованность ваших объектов. Вместо хранения значений, зависящих от других полей (и риска их устаревания) вы вычисляете их по запросу. Этот шаблон применим к любым производным данным: периметрам, средним значениям, форматированным строкам или любому значению, которое можно определить на основе существующих атрибутов.
Задание
ЛегкоДавайте создадим класс Box, который вычисляет свой volume по требованию! Вместо хранения volume в качестве поля вы создадите вычисляемое свойство, которое вычисляет его из dimensions box каждый раз, когда это необходимо.
Вы организуете код в двух файлах:
Box.lua: определите свой классBoxсо стандартным шаблоном prototype. Каждый box хранит три dimensions:width,heightиdepth. Включите:- конструктор
:new(width, height, depth), который сохраняет все три dimensions - метод
:getVolume(), который вычисляет и возвращает volume (width × height × depth) - метод
:getSurfaceArea(), который вычисляет и возвращает общую surface area
- конструктор
main.lua: используйте Require для подключения модуля Box, создайте instance box и продемонстрируйте, как вычисляемые свойства автоматически отражают текущие dimensions.
surface area box вычисляется по формуле: 2 × (width×height + height×depth + width×depth)
Вы получите три входных значения, представляющих dimensions box:
- Ширина
- Высота
- Глубина
В основном файле создайте box с заданными dimensions, затем выведите две строки:
- volume с помощью
:getVolume() - surface area с помощью
:getSurfaceArea()
Например, если входные значения — 3, 4 и 5, результатом должен быть:
60
94Преимущество вычисляемых свойств в том, что они всегда остаются точными. Если позже изменить одну из dimensions box, повторный вызов :getVolume() автоматически вернёт новое правильное значение: ручные обновления не нужны!
Попробуйте сами
-- Подключить модуль Box
local Box = require('Box')
-- Считать входные размеры
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())
-- TODO: Создать экземпляр box с заданными размерами
-- TODO: Вывести объём, используя :getVolume()
-- TODO: Вывести площадь поверхности, используя :getSurfaceArea()
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Концепция 'self'
Таблицы с функциямиЯвный 'self'Синтаксис с двоеточиемТочка против двоеточияИтоги — Движущаяся точка4Проект: Цифровой банк
Настройка проектаМетод пополнения7Полиморфизм и переопределение
Переопределение методовВызов родительских методовУтиная типизацияОбщий интерфейсПроверка типаИтоги — Роли сотрудников2Паттерн прототипа класса
Концепция прототипаСвязывание через __indexКонструктор :new()Инициализация атрибутовНезависимые экземплярыИтоги — Автозавод5Перегрузка операторов в ООП
Сложение объектовВычитание объектовКонкатенация объектовСравнение объектов (<, >)Повторение — Математика кошелька8Инкапсуляция
Соглашения об именованииЗамыкания для приватностиДоступ через замыканияТаблицы только для чтенияЛогика валидацииИтоги — Защищенное хранилище11Паттерны проектирования (Lite)
Фабричные функцииТаблица SingletonПаттерн IteratorObserver (Слушатель)Итоги — Logger Factory3Состояние и поведение объектов
Переменные экземпляраГеттерыСеттерыВычисляемые свойстваФорматирование строкПроверка на равенствоПовторение — Оценка студента6Основы наследования
Настройка наследованияНаследование методовРасширение конструктораДобавление дочерних методовОбщее и уникальноеИтоги: Иерархия фигурПотренируйтесь самостоятельно: Онлайн-компилятор Lua