在Lua中定义表成员函数的方式

据我所知,在Lua中有多种方法可以为表定义成员函数。例如,以下两种方法似乎是等效的:

-- 方法a)
local table1 = {x = 1, y = 2}
function table1:myfunc()
    return self.x + self.y
end

-- 方法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()语法和冒号)不可用?

点赞
用户3574628
用户3574628

作为一个函数式编程爱好者,我更喜欢方法b,因为它一次性定义了整个表,而不是为每个需要添加的方法都进行一次变异。你需要注意的一件事是,有些方法可能会相互调用,使用局部变量比调用“self:myfunc()”更快。

local function myfunc(self)
  return self.x + self.y
end

local myTable = {
  x = 1,
  y = 2,
  myfunc = myfunc,

  moreMyfunc = function(self)
    return myfunc(self) * 2
  end,
}

如果方法之间的不对称让你感到困扰,可以将所有方法都设为局部变量,并在表构造器中添加,就像我刚刚用“myfunc”做的那样。

Egor提出了另一个重要的观点(如果表是类,则更相关):

方法a允许你从函数内部作为上值访问变量table1。 方法b不允许这样做。

在这种情况下,我会提前声明表名。这样做的好处是只需要更改一个变量,而不是多次变异表。

local myTable

local function myfunc(self)
  return self.x + self.y
end

local function moreMyfunc(self)
  return myfunc(self) * 2
end

myTable = {
  x = 1,
  y = 2,
  myfunc = myfunc,
  moreMyfunc = moreMyfunc,
}
2019-02-21 17:52:50