Lua:如何将方法连接起来,就像字符串方法一样?

字符串函数可以用以下方式之一来使用:

string.FUNCTION('myString', 参数)

或者替换 'string' 为要使用的字符串,然后将其作为方法调用

('myString'):METHOD(参数)

最后一种方法非常易读,并允许连接方法。

-- 示例字符串操作
some_str, pos = '   some string', 1
-- 默认字符串语法
while string.find(string.sub(some_str, pos, pos), '%s') do pos = pos +1 end
-- 使用语法糖相同的操作
while some_str:sub(pos, pos):find('%s') do pos = pos +1 end

所以我尝试使用自己的函数来获得相同的行为。但是这失败了。 我发现的唯一方法是使用一个额外的参数来表示:返回对象本身还是结果。 这里有一个简单的例子。

calc = {
    result = 0,
    operator = '',
    run = function(self, a, b, r) -- 返回带有 r ='s' 的 self
        if b == 's' then r, b = b, nil end
        if not b then b, a = a, self.result end
        if self.operator == '+' then self.result = (a) + (b)
        elseif self.operator == '-' then self.result = (a) - (b)
        elseif self.operator == '*' then self.result = (a) * (b)
        elseif self.operator == '/' then self.result = (a) / (b) end
        if r ~= nil then return self else return self.result end
    end,
    add = function(self, a, b, r) self.operator = '+' return self:run(a, b, r) end,
    sub = function(self, a, b, r) self.operator = '-' return self:run(a, b, r) end,
    mul = function(self, a, b, r) self.operator = '*' return self:run(a, b, r) end,
    div = function(self, a, b, r) self.operator = '/' return self:run(a, b, r) end
}

-- 单个操作
result = calc:add(12, 5)

-- 连接操作
result = calc:add(12, 5, 's'):sub(3, 's'):mul(2, 's'):div(7)

是否存在与字符串操作相同的方法? 提前感谢。

点赞
用户936986
用户936986

你随后的调用将's'赋值给'b'参数,而不是'r'。当然,检查'return self'失败了。与其给带有某些标志的方法提供不同的行为,不如使它们总是返回'self',并制作一个单独的方法来返回当前结果 - 这样更容易阅读和编程。

之后,您的调用将如下所示:

result = calc:new(12):add(5):sub(3):mul(2):div(7):result()

此外,你真的不需要进入一个将分裂成'if'的大函数的代理函数 - 只需要在'add'/'sub'/'mul'/'div'本身内部完成所有工作即可。

您可能还需要多个calc对象,每个对象都有自己独立的当前结果。在metatable中存储常见函数,并使':new'创建新实例,并为结果分配一个单独的条目。

local calc_meta = { __index = {
    add = function(self, number) self._r = self._r + number return self end,
    sub = function(self, number) self._r = self._r - number return self end,
    mul = function(self, number) self._r = self._r * number return self end,
    div = function(self, number) self._r = self._r / number return self end,
    result = function(self) return self._r end
}}

local calc = {
    new = function(self, number)
    return setmetatable({
        _r = number or 0
    }, calc_meta) end
}

result = calc:new(12):add(5):sub(3):mul(2):div(7):result()
print(result)
-- 4

您无法完全复制Lua的字符串行为 - 它内置在VM中,将'string'表视为字符串值的metatable,并且无法在不修改VM本身的情况下进行编程。但是,如果将'__add'/'__sub'和其他数字方法添加到metatable中,以便它们自动"解包"您的对象到基本数字值,您可以摆脱最终的额外'result'。当然,之后您将无法将您的方法应用于"解包"值。

2016-02-28 11:13:03