改变对象的 metamethods
有
local Class = {}
Class.__meta = {__index=Class}
function Class.new() return setmetatable({}, Class.__meta)
假设我们想要使用 metatable 改变单个实例 object = Class.new()
的行为,
有一些错误需要避免:
setmetatable(object, {__call = table.concat}) -- WRONG
这将旧的 metatable 与新的 metatable 交换,从而打破了类的继承
getmetatable(object).__call = table.concat -- WRONG AGAIN
请记住,表值仅供参考; 实际上,对象的所有实例只有一个实际表,除非构造函数定义为 1 ,因此通过这样做我们修改了类的所有实例的行为。
这样做的一种正确方法:
不改变类:
setmetatable(
object,
setmetatable(
{__call=table.concat},
{__index=getmetatable(object)}
)
)
这是如何运作的? - 我们在错误#1 中创建了一个新的 metatable,但是我们不是将它留空,而是为原始 metatable 创建一个软拷贝。可以说新的 metatable 从原始的继承,好像它本身就是一个类实例。我们现在可以覆盖原始元表的值而无需修改它们。
改变类:
1 号(推荐):
local __instance_meta = {__index = Class.__meta}
-- metatable for the metatable
-- As you can see, lua can get very meta very fast
function Class.new()
return setmetatable({}, setmetatable({}, __instance_meta))
end
2(少推荐):见 1
1 function
Class.new() return setmetatable({}, {__index=Class}) end