在__indexed时,使表格像值一样的优雅方式?

时间:2015-06-24 10:37:20

标签: oop inheritance lua

我的自制OO设计遇到了这个特殊问题:

Entity = {}
function Entity:new(o)
  o = o or {}
  return setmetatable(o, {__index = Entity})
end
function Entity:init() end
function Entity:think() end
function Entity:spawn()
  --put in entity pool and begin drawing/logic
  self:init()
end

Block = Entity:new{
  x = 0,
  y = 0,
  color = {255, 255, 255, 255},
}
function Block:getPos()
  return self.x, self.y
end
--setPos, getColor, setColor etc
function Block:init()
  self:setColor(math.random(255), math.random(255), math.random(255))
end

a = Block:new()
a:spawn() --a new block with a random color
--a few seconds later...
b = Block:new()
b:spawn() --all blocks change to new color

所有原型和实例共享color表。如何使该表的行为类似于字符串:

a = {table}
b = a
print(b[1]) -->table
a[1] = "object"
print(a[1], b[1]) -->object, table

与对象相反:

a = {table}
b = a
print(b[1]) -->table
a[1] = "object"
print(a[1], b[1]) -->object, object

TL; DR:我需要创建一个新的数据类型。

2 个答案:

答案 0 :(得分:2)

有三种方法可以解决您的问题:

  1. Entity.color对象初始化期间初始化Entity表 - 将其放入Entity:new()函数。
  2. Entity.color表替换为代表其内容的四个变量 - Entity.colorredEntity.colorgreenEntity.colorblueEntity.coloralpha
  3. Entity:setColor()创建一个包含新值的新self.color表,而不是直接修改这些值。 self.color = {red, green, blue, alpha}代替self.color[1] = red; self.color[2] = green; self.color[3] = blue; self.color[4] = alpha

答案 1 :(得分:0)

  

如何使该表的行为类似于字符串:

您的示例涉及将Lua变量赋值更改为复制而不是引用。即使你能够影响Lua中的这种变化(你也不能),这将是一个难以形容的可怕想法。

  

所有原型和实例共享颜色表。

因为你把它放在原型中(例如"类"),所以它等同于OOP语言中的静态成员,由所有实例共享。如果您希望它是实例变量,那么它需要是实例构造的一部分,而不是构造。您也需要对xy执行相同的操作,否则它们也会被所有Block个实例共享。

function Block:new()
  local instance = { x = 0, y = 0 }
  instance:setColor(math.random(255), math.random(255), math.random(255))
  return setmetatable(instance, {__index = self})
end

您可以对构造函数进行增强,例如传入参数(例如初始化xy等),但重要的部分是实例带有自己的状态

Entity:spawn简单地调用init本身是没有意义的。您显示的示例代码表明它实际上应该生成新实例,但实现不会这样做。