使表在被索引时像值一样的优雅方式是什么?

我在我的homebrew 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()
  --将实体放进实体池并开始绘制/逻辑
  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等等
function Block:init()
  self:setColor(math.random(255), math.random(255), math.random(255))
end

a=Block:new() a:spawn() -->颜色随机的新方块

几秒钟之后... b=Block:new() b:spawn() -->所有方块改变为新颜色

所有原型和实例都共享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:我需要创建一种新的数据类型。**

点赞
用户1512226
用户1512226

下面有三种修复问题的方法:

1.在 Entity:new() 函数中进行 Entity 对象初始化时初始化 Entity.color 表格。 2.用四个变量 Entity.colorredEntity.colorgreenEntity.colorblueEntity.coloralpha 替换 Entity.color 表格,以表示它的内容。 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

2015-06-24 11:25:58
用户501459
用户501459

如何让该表像字符串一样运作:

你的例子涉及将 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 函数没有任何意义。你展示的示例代码表明它实际上应该生成新实例,但是实现并没有这样做。

2015-06-24 17:12:52