lua是否有内置的“事件处理程序”,或者它是否有可用的lib? 这就是一个例子,当“a = 100”事件发生时. 别的东西,而不是使用: while true do if a == 100 then [...] break; endend 或者只是为它添加
这就是一个例子,当“a = 100”事件发生时.
别的东西,而不是使用:
while true do if a == 100 then [...] break; end end
或者只是为它添加一个睡眠. “虽然真的这样做”只是一个例子,但它是一个可怕的例子.
Lua在单线程中运行,因此任何检查都必须由您的代码明确执行.在变量改变时立即执行代码的行为被称为“观看”.
如果您在每个帧(例如游戏)运行一组代码的环境中进行编程,则可以手动检查.
例如:
WatchedVariables = { a = 5, b = 22, } WatchedVariables_cache = {} for k,v in pairs(WatchedVariables) do WatchedVariables_cache[k] = v end function OnFrame() print("NEXT FRAME! (possibly 1 second later or something)") for k,v in pairs(WatchedVariables) do local v_old = WatchedVariables_cache[k] if v ~= v_old then -- this is the "callback" print(tostring(k).." changed from "..tostring(v_old).." to "..tostring(v)) WatchedVariables_cache[k] = v end end end function SomeFunctionThatOperatesSomeTime() print("about to change a, brother!") WatchedVariables.a = -7 print("a is changed") end
在下一帧时,将执行回调代码(打印).
这种方法的缺点是在WatchedVariables.a设置为-7之后不立即打印回调代码,即:输出将是:
about to change a, brother! a is changed NEXT FRAME! (possibly 1 second later or something) a changed from 5 to -7
为了防止这种潜在的不良行为,可以使用setter函数,例如:
MyObject = { _private_a = 5, set_a = function(self, new_value_of_a) self._private_a = 5 -- callback code print("a set to "..tostring(new_value_of_a)) end, get_a = function(self) return self._private_a end } function SomeFunctionThatOperatesSomeTime() print("about to change a, brother!") MyObject:set_a(-7) print("a is changed") end
此代码的输出显示回调立即运行:
about to change a, brother! a set to -7 a is changed
为了使这更舒适,Lua提供了使这种行为对程序员透明的元数据.
例:
MyObject = { __privates = { a = 5, } } MyObject_meta = { __index = function(self, k) return rawget(self, "__privates")[k] end, __newindex = function(self, k, v) rawget(self, "__privates")[k] = v -- callback code print("a set to "..tostring(v)) end, } setmetatable(MyObject, MyObject_meta) function SomeFunctionThatOperatesSomeTime() print("about to change a, brother!") MyObject.a = -7 print("a is changed") end
此代码的输出将与上一个示例相同:
about to change a, brother! a set to -7 a is changed
这是您的示例案例的实现:
MyObject = { __privates = { a = 5, } __private_callback = function(self, k, ov, v) if k == "a" and v == "100" then print("a is 100!") end end } MyObject_meta = { __index = function(self, k) return rawget(self, "__privates")[k] end, __newindex = function(self, k, v) local privates = rawget(self, "__privates") local ov = privates[k] privates[k] = v rawget(self, "__private_callback")(self, k, ov, v) end, } setmetatable(MyObject, MyObject_meta) function SomeFunctionThatOperatesSomeTime() MyObject.a = -7 -- prints nothing MyObject.a = 100 -- prints "a is 100!" MyObject.a = 22 -- prints nothing end
为什么变量__privates和__private_callback前缀为两个下划线?在具有两个下划线的典型编程情况下不应该访问的私有成员的前缀是惯例.如果您熟悉面向对象的方法以及它在Java和C等语言中的实现,您将了解它与私有和受保护关键字的相似之处.
如果您熟悉C#语言,您可能会看到set_a / get_a和metatable实现与访问器(set / get)类似.