计算属性
本课属于 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计算属性能让对象保持一致。与其存储依赖其他字段的值(这样可能导致这些值过时),不如在需要时计算它们。这个模式适用于任何派生数据:周长、平均值、格式化字符串,或任何能根据现有属性确定的值。
挑战
简单让我们来创建一个 Box 类,按需计算它的体积!你不必把体积存储为字段,而是可以创建一个计算属性,在需要时根据盒子的尺寸计算体积。
你会把代码分别写在两个文件中:
Box.lua:使用标准原型模式定义Box类。每个盒子都存储三个尺寸:width、height和depth。其中包括:- 一个
:new(width, height, depth)构造函数,用于存储这三个尺寸 - 一个
:getVolume()方法,用于计算并返回体积(宽 × 高 × 深) - 一个
:getSurfaceArea()方法,用于计算并返回总表面积
- 一个
main.lua:引入你的 Box 模块,创建一个盒子实例,并演示计算属性如何自动反映当前尺寸。
盒子的表面积计算公式为:2 × (width×height + height×depth + width×depth)
你会收到三个输入,分别表示盒子的尺寸:
- 宽
- 高
- 深
在主文件中,使用给定的尺寸创建一个盒子,然后打印两行内容:
- 使用
:getVolume()获取的体积 - 使用
: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() 输出表面积
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器