我是一名学习Lua的C ++程序员,试图理解为什么需要getmetatable()和setmetatable()。
根据所有教程,如果我想在我的子类定义中的某个地方从“基类”(使用C ++概念)创建一个“子类”,我会有这样的东西:
1) setmetatable(subclass, getmetatable(baseclass))
但为什么呢?为什么不这样做:
2) setmetatable(subclass, baseclass)
或者为什么不将所有基类成员复制到子类中并使用元数据进行修改?
3) for k,v in pairs(baseclass) do
subclass[k] = v
end
毕竟,OOP在概念上,我所要做的就是让我的子类成为一种基类,然后添加一些差异。所以我先从基类的副本开始,然后做我的修改,使我的子类不同。
然后我突然意识到,也许metatables是共享实例。也就是说,具有相同元表的类共享内存中完全相同的元表。是对的吗?如果我在单个元表中更改数据元素,那么具有该元表的所有表都将经历相同的数据更改?如果我在metatable中有一个“counter”变量并将其递增,那么使用该metatable的所有类都将使该成员变量递增。
这就是所有教程中都没有明确的区别,以及是什么让metatable如此混乱。因此,用C ++术语来说,元数据是共享它们的类的静态成员。
但是上面的方法3仍然可以实现目标但是浪费,因为它创建了基类成员的副本而不是共享它们。
那么,这是一个创建子类的有效函数吗? (复制基类然后添加新成员以使其与基类不同)
local Developer = subclass(Person, { skillz = {"c++", "lua", "python"}})
function subclass(base, new_members)
local self = {}
setmetatable(self, getmetatable(base))
local mt = getmetatable(self)
for k,v in pairs(base) do -- replicate bases members that aren't in its metatable into us as our metatable
mt[k] = v
end
for k,v in pairs(new_members) do -- add new members or overrides that make us different than base!
mt[k] = v
end
return self
end