Lua类实例与嵌套表

简单的 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

-- 嘁嘁嚷嚷

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

Q1:我的面向对象实现是否有缺陷?我尝试了 LOOP,结果相同,我的逻辑中有根本性缺陷吗?

Q2:如何使每个 creature 实例都有自己的 stats 表(和子表)?

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

原文链接 https://stackoverflow.com/questions/2937621

点赞
stackoverflow用户206020
stackoverflow用户206020

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

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

Power,agility 等等会在构造函数中作为 stats 参数传递。

2010-05-30 09:58:13
stackoverflow用户88888888
stackoverflow用户88888888

因为在它们的元表中把类表设置为了__index,所以它可以这样运作(大多数实现方式是这样的)。所以如果你访问creatureA.stats(并且在creatureA上找不到stats,因此落到了__index上),那么它会返回creature.stats。也许你应该阅读一下Lua 5.1 参考手册:元表

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

你必须在你的类实现所使用的任何初始化函数中这样做:

creature = class
{
     __init = function(self, ...)
         self.stats = {power = 10, agility = 10, endurance = 10, filters = {}}
     end,
}
2010-05-30 10:20:26
stackoverflow用户41661
stackoverflow用户41661

class 不是 Lua 中的标准函数。您没有说您是从 Roberto 借用它,还是自己编写的,或其他情况。但我的猜测是,您想更改 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

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

2010-05-30 20:59:59
stackoverflow用户354668
stackoverflow用户354668

你那个名叫 class 的函数看起来很可疑。我会选择最简单的代码。这是一个庞大的类文件。它没有什么花里胡哨的东西,有些人可能会认为它缺少一些灵活性,但至少我下周也能读懂代码。

-- 类对象

monster = {}
monster.__index = monster 

-- 类方法

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  版权所有(C) 1994-2008 Lua.org, PUC-Rio
> require 'monster'
> m = monster.new('Katla')
> m:shout()
Aaaaaaa! My name is Katla!
2010-05-31 14:44:10