我正在Corona / Lua的一个游戏中工作,并实施了一个名为" Item"它代表了游戏中的武器,盔甲,护身符等。我是面向对象的Lua的新手。
在创建类的新实例后,我发现设置对象的某些属性似乎将它们设置在类metatable中,而不是在对象本身中。
这是类和构造函数:
local Item = {
name = nil,
itemType = nil,
scarcity = "basic",
baseDamage = 0, -- Bow only
bonuses = {
damageBonus = 0,
speedBonus = 0,
critBonus = 0,
dropBonus = 0,
rechargeBonus = 0,
xpBonus = 0
}
}
-- Creates a simple blank instance of the Item class.
function Item:new(o)
local item = o or {}
setmetatable(item, self)
self.__index = self
return item
end
现在让我说我根据这个原型创建了两个对象:
local bow = Item:new()
bow.itemType = "bow"
starterBow.baseDamage = 5
local ring = Item:new()
ring.itemType = "ring"
ring.bonuses.damageBonus = 0.25
令我沮丧的是," bonuses.damageBonus"属性似乎被设置在metatable中,因此适用于每个项目(即弓也获得伤害加值,并与环堆叠)。然而,这种行为似乎仅限于"奖金"属性。如果我设置" itemType"属性,它按预期附加到对象,而不是类。
我希望看到的行为是"奖金"可以为单个项目设置表格。知道我做错了什么吗?谢谢!
答案 0 :(得分:4)
当您尝试从表中“获取”不存在的字段时,会触发__index
元字段。
ring.bonuses.damageBonus = 0.25
试图从戒指“获得”奖金,因为它不存在,转到metatable并返回你的奖金表,然后将其damageBonus索引设置为0.25。
理解只是在Item表中声明变量并不意味着Item实例会将它们作为实例变量继承。为此,您需要在Item:new()函数中声明/初始化它们:
function Item:new(o)
local item = o or {}
setmetatable(item, self)
self.__index = self
item.bonuses={} -- create instance bonuses table and give default values
for k,v in pairs(self.bonuses) do
item.bonuses[k]=v
end
return item
end
答案 1 :(得分:3)
实例中不存在bonuses
表,因此查找它在metatable中查找并在__index
表中找到它。然后它继续在该表中查找。同样,作业也会做同样的事情。只有,这是关键,一个奖励表,但因为你永远不会复制它,唯一存在的副本是Item
类中的那个,然后通过__index
元表查找找到。
您需要将__index
metatable魔法添加到您为每个实例创建的bonuses
表中(对于默认值但是本地到实例的分配)或者只需复制/创建bonuses
每个实例都有一个表格。