添加对象
本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 26 课,共 70 课。
你已经了解了 __tostring 和 __eq 这样的元方法如何让你自定义对象的行为。现在,我们将把它扩展到算术运算,从加法开始。
当你在两个对象之间使用 + 运算符时,__add 元方法会定义发生什么。Lua 遇到 a + b 时,会在任一操作数的元表中查找 __add。
local Vector = {}
Vector.__index = Vector
function Vector:new(x, y)
local obj = {x = x, y = y}
setmetatable(obj, Vector)
return obj
end
function Vector.__add(v1, v2)
return Vector:new(v1.x + v2.x, v1.y + v2.y)
end注意,__add 是用点号定义的。Lua 会把两个操作数都作为普通参数传入,而点号形式会为它们分别命名。用冒号也可以,因为 function Vector:__add(other) 与 function Vector.__add(self, other) 相同,不过点号形式是惯例。__add 应该返回一个新对象,而不是修改任一原对象。这样可以让操作更可预测、更安全。
local a = Vector:new(3, 4)
local b = Vector:new(1, 2)
local c = a + b
print(c.x, c.y) -- 输出:4 6关键在于,__add 必须放在元表本身(这里是 Vector)中,而不能只放在对象中。由于我们将 Vector 设置为所有实例的元表,因此它们会自动共享这种行为。
挑战
简单我们来编写一个支持使用 + 运算符进行加法的 Vector 类。这是你学习运算符重载的第一步,它能让你的对象自然地使用 Lua 内置运算符。
你将把代码分成两个文件:
Vector.lua:定义包含x和y分量的 Vector 类。添加:new(x, y)构造函数,并实现__add元方法,让两个向量相加时生成一个分量合并后的新向量。定义__add时要使用点号,这样两个操作数都会作为具名参数传入。main.lua:引入 Vector 模块,创建向量实例,并演示相加后能得到正确结果。
你会收到 4 个输入:
- 第一个向量的 x 分量
- 第一个向量的 y 分量
- 第二个向量的 x 分量
- 第二个向量的 y 分量
在主文件中,使用给定的分量创建两个向量,用 + 运算符将它们相加,并将结果向量的 x 和 y 值分别打印在单独的行上。
例如,如果输入是 3、4、1、2,输出应为:
4
6第一个向量(3,4)加上第二个向量(1,2),等于一个新向量(4,6)。
亲手试试
-- 加载 Vector 模块
local Vector = require('Vector')
-- 读取输入
local x1 = tonumber(io.read())
local y1 = tonumber(io.read())
local x2 = tonumber(io.read())
local y2 = tonumber(io.read())
-- TODO:使用输入值创建两个 Vector 实例
-- TODO:使用 + 运算符将两个向量相加
-- TODO:将结果向量的 x 和 y 值分别打印在两行
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器