【发布时间】:2019-07-15 10:02:12
【问题描述】:
据我了解,有多种方法可以在 Lua 中为表定义成员函数。例如,以下两个似乎是等价的:
-- method a)
local table1 = {x = 1, y = 2}
function table1:myfunc()
return self.x + self.y
end
-- method b)
local table2 = {
x = 1,
y = 2,
myfunc = function(self)
return self.x + self.y
end,
}
以前使用过 Python,我的直觉是使用方法 b) 将事物更整齐地组合在一起。但是,通过示例阅读,似乎人们通常按照惯例使用方法 a)。不过,我找不到任何客观的理由来说明为什么它应该是优越的。
确实,相反,在初始化表时,至少有理由向前声明函数变量,如下所示:
local table3 = {x = 1, y = 2, myfunc}
function table3:myfunc()
return self.x + self.y
end
这样 Lua 从一开始就知道成员的存在,并且可以正确设置散列,而增加现有表的成员数量可能需要重新散列(尽管我无法想象这实际上会变成除非您对大量小表执行此操作,否则会出现明显的性能问题)。来源比较:https://www.lua.org/gems/sample.pdf
那么在定义表本身的过程中,有什么理由不直接定义成员函数呢?或者仅仅是因为某些语法糖(function name() 语法和冒号)不可用?
【问题讨论】:
-
table3示例并没有按照您的想法进行。表构造函数{}将复制要插入的值,读取变量myfunc并将其存储在索引[3]下。它不会创建稍后填写的myfunc条目。如果您想创建该条目,请编写myfunc = true,以分配不是nil的内容。但坦率地说,你不会在这里看到任何加速,只会浪费更多时间编写不需要的文本。另请注意,如果将所有方法函数存储在单独的表中,并将其设置为可对所有相同类型的对象进行元表处理,则更易于维护。 -
方法
a允许您从函数内部访问变量table1作为上值。方法b不允许这样做。 -
@Vlad 好吧,我想知道它应该如何区分前向声明和任何旧的未声明变量。并且看到
table.member相当于Lua 中的table["member"],我猜table3 = {1 = 1, y=2, "myfunc"}也可以解决问题,对吧? -
@EgorSkriptunoff 很公平,但是通过
self不会达到同样的效果吗? -
@Vlad 再想一想,它可能不会成功,因为 Lua 仍然会将字符串存储在索引 3 下……