具有嵌套表的Lua类实例

时间:2010-05-30 05:07:03

标签: class oop lua nested lua-table

简单的Lua游戏,简单的类似:

creature = class({ 
name = "MONSTER BADDY!",

stats = { power = 10, agility = 10, endurance = 10, filters = {} },

other_things = ...
})

creatureA = creature.new()

creatureB = creature.new()

creatureA.name = "Frank"

creatureB.name = "Zappa"

creatureA.stats.agility = 20

creatureB.stats.power = 12

- 等等等等等等

非表值是每个实例的个别值,但表值是 在所有实例之间共享,如果我在一个实例中修改stats.X值, 所有其他实例都看到相同的统计表。

Q1:我的OO实施是否有缺陷?我尝试了LOOP并发生了同样的结果, 我的逻辑中有一个根本的缺陷吗?

Q2:你如何让每个生物实例拥有自己的统计表(和子表)?

PS。我不能展平我的类表,因为它比示例更复杂,并且使用这种嵌套的表实现简化了代码的其他部分。

4 个答案:

答案 0 :(得分:3)

它的工作方式与此类似,因为类实例在其metatable中将类表设置为__index(好吧,大多数实现以这种方式工作) 因此,如果您访问creatureA.stats(并且在stats上找不到creatureA,则会落在__index),则会返回creature.stats。 也许你应该阅读Lua 5.1 Reference Manual: Metatables

您将无法在类的表构造函数中声明每个实例变量(除非您将类表中的所有内容深度复制到实例,这将非常昂贵)

您必须在类实现使用的任何初始化函数中执行此操作:

creature = class
{
     __init = function(self, ...)
         self.stats = {power = 10, agility = 10, endurance = 10, filters = {}}
     end,
}

答案 1 :(得分:3)

class不是Lua中的标准函数。你不是说你是从罗伯托借来的,是自己的,还是什么的。但我的猜测是你要更改new方法,以便它对原型进行深层复制而不是浅层复制:

function deep_copy(v)
  if type(v) == 'table' then
    local u = { }
    for k, v in pairs(v) do
      u[k] = v
    end
    setmetatable(u, getmetatable(v))
    return u
  else
    return v
  end
end

(警告:我没有尝试编译此代码,更不用说运行它了。)

答案 2 :(得分:0)

创建新的creature时,如果您不希望它被共享,您可以随时为其创建一个新的stats表。

creature = class({ 
    name = "MONSTER BADDY!",
    stats = stats.new({ power = 10, agility = 10, endurance = 10, filters = {} }),
    other_things = ...
})

权力,敏捷性等将作为stats的构造函数中的参数传递。

答案 3 :(得分:0)

你的名为 class 的功能看起来很可疑。我会选择最简单的代码。这是一个怪物类文件。没有什么花哨的,有些人会说它缺乏一些毛病,但至少我也可以在下周自己阅读这些代码。

-- Class object

monster = {}
monster.__index = monster

-- Class methods

function monster.new(name)
    local o = {}
    o.name = name
    o.stats = {power = 10, agility = 10, endurance = 10, filters = {}}
    setmetatable(o, monster)
    return o
end

function monster:shout()
    print('Aaaaaaa! My name is ' .. self.name .. '!')
end

这是输出:

> lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require 'monster'
> m = monster.new('Katla')
> m:shout()
Aaaaaaa! My name is Katla!