Menu
CoddyTech

计算属性

本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 15 课,共 70 课。

getter 和 setter 可以访问已存储的值,但有时你需要的数据并不存在于已存储的字段中。它需要根据其他属性计算得出。这些属性称为计算属性。

考虑一个矩形。你保存了它的宽和高,但面积没有保存在任何地方,而是通过将这两个值相乘计算得出。你没有保存冗余数据,而是创建了一个用于计算并返回结果的方法:

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 类,按需计算它的体积!你不必把体积存储为字段,而是可以创建一个计算属性,在需要时根据盒子的尺寸计算体积。

你会把代码分别写在两个文件中:

  • Box.lua:使用标准原型模式定义 Box 类。每个盒子都存储三个尺寸:width、height 和 depth。其中包括:
    • 一个 :new(width, height, depth) 构造函数,用于存储这三个尺寸
    • 一个 :getVolume() 方法,用于计算并返回体积(宽 × 高 × 深)
    • 一个 :getSurfaceArea() 方法,用于计算并返回总表面积
  • main.lua:引入你的 Box 模块,创建一个盒子实例,并演示计算属性如何自动反映当前尺寸。

盒子的表面积计算公式为:2 × (width×height + height×depth + width×depth)

你会收到三个输入,分别表示盒子的尺寸:

  1. 宽
  2. 高
  3. 深

在主文件中,使用给定的尺寸创建一个盒子,然后打印两行内容:

  1. 使用 :getVolume() 获取的体积
  2. 使用 :getSurfaceArea() 获取的表面积

例如,如果输入是 3、4 和 5,输出应为:

60
94

计算属性的优点是,它们始终保持准确。如果之后你更改了盒子的某个尺寸,再次调用 :getVolume() 就会自动返回正确的新值,无需手动更新!

亲手试试

-- 加载 Box 模块
local Box = require('Box')

-- 读取输入的尺寸
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())

-- TODO:用给定的尺寸创建一个盒子实例

-- TODO:使用 :getVolume() 输出体积

-- TODO:使用 :getSurfaceArea() 输出表面积
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Lua 在线编译器