在函数上定义属性与在函数.prototype上定义属性

tl;dr 如果你熟悉javascript的工作原理,请跳到“问题”部分。

我来自javascript,在那里我们使用原型链来定义我们的“class”方法,例如:

function MyClass(){
    return this
}
MyClass.prototype.method = function(){
    // do stuff
}
MyClass.directPropFunction = function(){
    // do direct stuff
}

MyClass.method()                    // 不起作用
MyClass.directPropFunction()        // 起作用
new MyClass()                       // 从所述“class”实例化对象
new MyClass().method()              // 现在它起作用了!
new MyClass().directPropFunction()  // 但现在不再起作用了。

换句话说,在函数上定义直接属性可以被认为是“静态”方法,而在原型上定义属性可以被认为是常规方法。所有这些都建立在我们通过使用函数作为对象的构造函数来“伪造”类然后访问它们并使用它们的原型链来完成魔术事情的事实上。

一个重要的事情需要注意的是,甚至在原型上声明的.method也不是为对象的每个实例创建的。LUA是否有扩展函数对象的“适当”方式?

问题:

我在LUA中搞了一些事情,遇到了这个问题:我不知道它的内部工作原理,有什么区别和做事的首选方式是什么?另外,我不确定LUA是否具有整个“伪造”类,但我可能不会使用它,因此以下显示的哪种方法是“正确”的?

function Foo()
    -- do stuff
end
Foo.method = function()
    -- do stuff
end
Foo.prototype.protoMethod = function()
    -- do stuff
end

我想要达到的是以下内容:

function doSomething()
    -- does something, duh
    -- return uniqueID
end
doSomething.revert = function(uniqueID)
    -- reverts stuff
end

然后我将能够同时执行以下操作:

local a = doSomething()
doSomething.revert(a)

那么正确的方法是什么?

点赞
用户6632736
用户6632736

考虑以下练习:

local function reversible (func)
    local states = {}
    states [func] = states [func] or {}
    return function (...)
        local result = func (...)
        states [func] [result] = {...}
        return result
    end, function (result)
        return unpack (states [func] [result])
    end
end

local square, root = reversible (function (a)
    return a ^ 2
end)

local initial = -2
local squared = square (initial)
local reversed = root (squared)

io.write ('initial = ' .. tostring (initial) .. ', squared = ' .. tostring (squared) .. ', reversed = ' .. tostring (reversed) .. '\n')

当然,在这个例子中,被恢复的“状态”仅由函数参数组成;因此,func 必须是纯函数。假定原始函数只返回一个值(如果返回多个值,则 states 应该用 func 的结果的哈希值打包到一个表中进行索引)。

与 JavaScript 不同,在 Lua 中函数没有属性,对象没有原型。然而,Lua 表具有元表(metatables)。

此外,如果表的元表具有 __call 字段,则可以通过表字段来模拟函数属性,当表被像函数一样调用时使用。下面的例子实现了伪属性 revert 并且允许多个返回值的原始函数:

local function hash (array)
    return table.concat (array, ',')
end

local function reversible (func)
    local states = {}
    states [func] = states [func] or {}
    local wrapped = {
        revert = function (...)
            return unpack (states [func] [hash {...}])
        end
    }
    setmetatable (wrapped, {
        __call = function (tbl, ...)
            local results = {func (...)}
            states [func] [hash (results)] = {...}
            return unpack (results)
        end
    })
    return wrapped
end

local square = reversible (function (a)
    return a ^ 2
end)

print ('square (-2)', square (-2))
print ('square.revert (4)', square.revert (4))
2020-10-19 18:34:26