Menu
Coddy logo textTech

Вычисляемые свойства

Часть раздела Объектно-ориентированное программирование путешествия по 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

Вычисляемые свойства поддерживают согласованность ваших объектов. Вместо хранения значений, зависящих от других полей (и риска их устаревания) вы вычисляете их по запросу. Этот шаблон применим к любым производным данным: периметрам, средним значениям, форматированным строкам или любому значению, которое можно определить на основе существующих атрибутов.

challenge icon

Задание

Легко

Давайте создадим класс 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:

  1. Ширина
  2. Высота
  3. Глубина

В основном файле создайте box с заданными dimensions, затем выведите две строки:

  1. volume с помощью :getVolume()
  2. 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()
quiz iconПроверьте себя

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

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

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