在Lua中将数组作为函数参数传递?

5
我正在尝试修改我在这个视频中找到的示例类,使其更加流畅易用。希望我的注释足够清楚地解释了我想要实现的目标。问题是当我尝试使用数据表时,它会给我一个错误:lua: class example.lua:7: attempt to index field 'data' (a nil value)。
我猜这意味着数组没有被正确地传递到函数中,但我不知道为什么。我非常菜鸟Lua。
以下是我的代码:
local enemy = {}; --enemy class table

function enemy:New(data)
  local object = {}; --table to store all of data within class
  local len = # data --get length of passed table
  for i = 1, len, 2 do --loop to input all data from passed table into object table
    object.data[i] = data[i + 1];
  end

  function object:getData(choice) --function that allows us to retrieve data from the class
    return self[choice];
  end

  return object; --return class data table so we can create objects using the class
end

local monsterdata = {"name", "monster", "x", 64, "y", 128, "hp", 4}; --table containing data of monster. keys are odd numbered, values to those keys are even numbered
local monster = enemy:New(monsterdata); --create a object using the class

local test = monster:getData("x"); --set variable to a value with the getData function

print(test);
3个回答

5

您没有创建object.data表--Lua中的每个表都需要初始化:

local object = {}
local object.data = {}

或者

local object = { data = {} }

然而,如果您不修复getData函数,则您的示例将无法按预期方式工作:
function object:getData(choice) 
  return self.data[choice]
end

最后,这是Lua语言,所以你的代码中不需要任何; :P。

哈哈,我知道分号不是必须的,我刚开始学习C编程,我的老师对这些事情非常严格,所以保留它们让我感到安心。 :P - Lemony Lime
我一开始所做的事情是有效的(除了mkluwe指出的愚蠢错误),代码比这少,也不需要再次保存数据表。有没有任何理由让我选择这种方式而不是其他方式? - Lemony Lime

4
如果你希望object保存数据,你可能想要写成:
object[data[i]] = data[i + 1];

替代

object.data[i] = data[i + 1];

这样做的结果输出是64


啊,这是一个如此简单的错误……虽然我想通常都是这种情况。 - Lemony Lime
是的,这并不罕见。有时我会打t.a而不是t[a] - mkluwe

2
像其他人说的一样,object.data需要初始化,并且for循环和getData中存在缺陷。此外,虽然这不是一个bug,但在Lua中,将键作为奇数和值作为偶数传递的系统是C语言中非常好的方法,没有关联数组/字典/表文字,但在Lua中,惯用法是 {keyname = value, keyname = value, ...},如果表跨越多行,可以使用该方法。
{
    keyname = value;
    keyname = value;
    keyname = value;
    ...
}

所以在您的情况下,monsterdata 可以简单地表示为:
{
    name = "monster";
    x = 64;
    y = 128;
    hp = 4;
}

你可以完全移除 for 循环。

注意:这种方式只能表示字符串类型的键。对于其他类型的键,比如数字、布尔值、甚至函数和其他表格,需要用方括号[]将键包围起来。例如,如果你想要一个名为mynot的表,将布尔值映射到它们的相反值,你可以使用:

{
    [true] = false;
    [false] = true;
}

或者,如果您想将一组函数映射到它们的库。
{
    [print] = "standard";
    [os.execute] = "standard os";
    [math.sin] = "standard math";
    [function() print "a user function" end] = "me!";
}

我认为你学习越多关于Lua的知识,你就会越喜欢它。这是一门非常棒的语言,拥有许多有趣的小特性。愉快编码!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接