我有分数表,它存储分数,分数与其元表相关联。
fraction.add
是元操作 (__add
)。
问题就在这里。我想计算 x + y。
如果 x 和 y 都是分数,那么对其求值就没有问题。它通过
farction.add
进行评估。
如果x和y都是数字,不是分数,那么就是简单的数字加法,与分数无关。
如果 x 是分数,y 是非分数(反之亦然),那么我想将分数 x 转换为数字并将其添加到 y。我当然可以轻松地将分数转换为数字,但问题在于与
__add
相关的分数的 fraction.add
元表。仅当 x 和 y 均为分数时才有效。它会抛出错误,因为 y 不是分数。所以我正在寻找一种逻辑来处理当一个是分数而另一个是非分数时的情况。 if else 在元表中可能很简单,但我无法做到。任何想法都会很有帮助。
fraction
“类”并对此提供支持。就像检查 a, b
元方法的参数 __add
的类型并根据需要将它们转换为分数一样简单。
或者,举一个更简单的例子,它忽略了几点:
local fraction_mt = {}
local function new_fraction(numerator, denominator)
assert(numerator % 1 == 0)
assert(denominator % 1 == 0)
return setmetatable({numerator = numerator, denominator = denominator}, fraction_mt)
end
local function add_fractions(a, b)
-- Note: No care is taken to shorten the resulting fraction here.
return new_fraction(a.numerator * b.denominator + b.numerator * a.denominator,
a.denominator * b.denominator)
end
function fraction_mt.__add(a, b)
if type(a) == "number" then
a = new_fraction(a, 1)
elseif type(b) == "number" then
b = new_fraction(b, 1)
end
return add_fractions(a, b)
end
function fraction_mt:__tostring()
return ("%d/%d"):format(self.numerator, self.denominator)
end
print(new_fraction(1, 2) + new_fraction(1, 2)) -- 4/4
print(new_fraction(1, 2) + 1) -- 3/2
print(1 + new_fraction(1, 2)) -- 3/2
请注意,即使只有一个操作数不是数字,Lua 也会调用
__add
(请参阅参考手册):
如果加法的任何操作数不是数字,Lua将尝试调用元方法。它首先检查第一个操作数(即使它是一个数字);如果该操作数没有为 __add 定义元方法,那么 Lua 将检查第二个操作数。如果Lua能找到一个元方法,它就会以两个操作数为参数调用该元方法,调用的结果(调整为一个值)就是操作的结果。否则,如果没有找到元方法,Lua 会引发错误。