Menu
Coddy logo textTech

Calculated Properties

Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 15 of 70.

Getters and setters provide access to stored values, but sometimes you need data that doesn't exist as a stored field—it needs to be calculated from other attributes. These are called calculated properties.

Consider a rectangle. You store its width and height, but the area isn't stored anywhere—it's computed by multiplying these two values together. Instead of storing redundant data, you create a method that calculates and returns the result:

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

The :getArea() method doesn't return a stored value—it computes the area fresh each time you call it. This approach has a key advantage: if the width or height changes, the area automatically reflects the new dimensions without you needing to update anything.

local box = Rectangle:new(5, 3)
print(box:getArea())  -- Output: 15

box.width = 10
print(box:getArea())  -- Output: 30

Calculated properties keep your objects consistent. Rather than storing values that depend on other fields (and risking them becoming outdated), you compute them on demand. This pattern applies to any derived data—perimeters, averages, formatted strings, or any value that can be determined from existing attributes.

challenge icon

Challenge

Easy

Let's build a Box class that calculates its volume on demand! Instead of storing the volume as a field, you'll create a calculated property that computes it from the box's dimensions whenever it's needed.

You'll organize your code across two files:

  • Box.lua: Define your Box class with the standard prototype pattern. Each box stores three dimensions: width, height, and depth. Include:
    • A :new(width, height, depth) constructor that stores all three dimensions
    • A :getVolume() method that calculates and returns the volume (width × height × depth)
    • A :getSurfaceArea() method that calculates and returns the total surface area
  • main.lua: Require your Box module, create a box instance, and demonstrate how the calculated properties automatically reflect the current dimensions.

The surface area of a box is calculated as: 2 × (width×height + height×depth + width×depth)

You will receive three inputs representing the box's dimensions:

  1. Width
  2. Height
  3. Depth

In your main file, create a box with the given dimensions, then print two lines:

  1. The volume using :getVolume()
  2. The surface area using :getSurfaceArea()

For example, if the inputs are 3, 4, and 5, the output should be:

60
94

The beauty of calculated properties is that they always stay accurate. If you later changed one of the box's dimensions, calling :getVolume() again would automatically return the correct new value—no manual updates needed!

Cheat sheet

Calculated properties are methods that compute and return values based on other attributes rather than storing them directly. This ensures data consistency and eliminates redundancy.

Example of a calculated property for 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

The :getArea() method calculates the area each time it's called, automatically reflecting any changes to width or height:

local box = Rectangle:new(5, 3)
print(box:getArea())  -- Output: 15

box.width = 10
print(box:getArea())  -- Output: 30

Calculated properties are useful for any derived data such as perimeters, volumes, averages, or formatted strings that can be determined from existing attributes.

Try it yourself

-- Require the Box module
local Box = require('Box')

-- Read input dimensions
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())

-- TODO: Create a box instance with the given dimensions

-- TODO: Print the volume using :getVolume()

-- TODO: Print the surface area using :getSurfaceArea()
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming