2017-06-01 61 views
1

我想创建一个包含另一个表的功能,像这样的表:如何在Lua中创建方法的映射?

party_animal = {} 

function party_animal:dance() 
    -- dance 
end 

function party_animal:dance_furiously() 
    -- extreme dance 
end 

method_map = { 
    'idea_one': party_animal:dance, 
    'idea_two': party_animal:dance_furiously, 
} 

然后,这个我可以援引的这样的一个功能:method_map[1][2]()。当我使用.运营商代替:时,我可以得到此工作,但我想访问self

我得到的错误是这样的:

stdin:2: '}' expected (to close '{' at line 1) near ':' 
+0

method_map [1] [2]。 method_map [1]为零,因此你不能索引method_map [2]。即使method_map [1]是一个表,method_map [1] [2]也是零,你也不能调用nil值。 – Piglet

+0

这是由于我使用错误的表格语法? – Matt

+1

@MattDeacalionStevens不,这是因为您在创建表格时尝试使用字符串键并尝试使用数字键访问值。 'table [1]'尝试访问使用'table [1] = foo'或'table = {foo}'定义的键。总之,如果你省略'{}'中的键,那么所有的值将被编号为从* 1 *开始的数字。 'table = {“a”,“b”,“c”}'将导致'table [1] ==“a”'。 – Green

回答

4

从Lua的参考手册:https://www.lua.org/manual/5.3/manual.html#3.4.9

表构造器是创建表的表达式。每次评估构造函数时,都会创建一个新表。构造函数可以是 ,用于创建空表或创建表并初始化其字段的某些 。对构造的一般语法

tableconstructor ::= ‘{’ [fieldlist] ‘}’ 
fieldlist ::= field {fieldsep field} [fieldsep] 
field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp 
fieldsep ::= ‘,’ | ‘;’ 

形式[EXP1] = EXP2中的每一个字段添加到新的表中的条目与 键EXP1和值EXP2。表单name = exp的字段为 ,等效于[“name”] = exp。最后,表单exp的字段为 ,等同于[i] = exp,其中i是连续的整数,从1开始 ,其他格式的字段不影响此计数。

正如你看到类似

method_map = {'idea_one' : party_animal:dance} 

是不可能的,因为它为表构造无效语法。

替换:with =并移除“'使其成为有效的表达式。

method_map = {idea_one = party_animal:舞蹈}将避免该错误消息

标准输入:2: '}' 预期(以关闭 '{' 在第1行)邻近 ':'

但是你会看到关于缺少函数参数的另一个错误信息。

这是因为冒号操作符只对函数调用和定义有效。不适用于您实际想要执行的表格元素索引。

method_map = {idea_one = party_animal.dance}不会导致任何错误。

当然,你不能通过自己访问party_animal。

我们该如何做到这一点?调用method_map:dance()将自引用method_map。

但是,如果我们使用语法糖用冒号运算符, 写

method_map = {idea_one = function() return party_animal.dance(party_animal) end}

或等值

method_map = {idea_one = function() return party_animal:dance() end}

我们终于得到我们想要的东西。

现在自我将把party_animal如果我们调用method_map:dance()

+1

最后一个例子可以改为'method_map = {idea_one = function()return party_animal:dance()end}'。 – nobody

+0

@当然没有人哦。我添加了可选的语法糖版本 – Piglet

4
party_animal = {} 

function party_animal:dance() 
    -- dance 
end 

function party_animal:dance_furiously() 
    -- extreme dance 
end 

method_map = { 
    idea_one = party_animal.dance, 
    idea_two = party_animal.dance_furiously, 
} 

如预期这将工作。为什么?

首先,请注意您的表格主体已被更改为匹配lua语法。您得到的错误是由Piglet以非常详细的方式指出的无效表定义引起的。

其次,功能

function table:foo() end 

这个定义是相同的,因为这一个

function table.foo(self) end 

传递函数参照不改变其参数。第一个参数仍然是self,如果您使用:调用此函数,则method_map将作为self传递。

如果你想有party_animalselfmethod_map功能,您将需要使用额外的功能:

method_map = { 
    idea_one = function (...) return party_animal.dance(party_animal, ...) end, 
    idea_two = function (...) return party_animal.dance_furiously(party_animal, ...) end, 
} 

Lua 5.3 Reference Manual on function defining and calling

+0

我想他想通过自己访问party_animal。在你的例子中,self会引用method_map。同样使用表格作为表格名称并不是很好,因为它已经用于提供Luas标准表格操作库。 – Piglet

+0

@Piglet我对此有不同的理解:他担心没有':'的传递函数会导致无法访问'self'。那么我想我们应该等他。 – Green

+0

谢谢,这些彻底的解释是辉煌的!这两者都有点,我想传递一个表值作为回调函数,但我希望函数能够访问'self' ...我明白':'操作符做到了这一点,但我无法得到它上班。 @ Piglet的答案的最后一点是现货! – Matt