Lua函数和冒号的区别

10

我对lua语法的理解有些困难,因此希望得到一些权威参考资料来帮助我和其他人更好地学习。

function blah()

并且

function classname:blah()

2
可能是What does ":" mean in Lua的重复问题。 - Yu Hao
如果编辑一下,把这个问题变成一个问题,我认为它会更好。 :-) - EJ Mak
2个回答

27

Aubergine18的帖子已经回答了这个问题,但我会从最基本的原理解释一下,以提供更进一步的澄清。

在Lua中,函数是值,就像字符串或数字一样。这个表达式:

function() end

创建一个函数值。您可以将其分配给变量,就像分配任何其他值一样:
foo = function() end

Lua提供多种简写语法,也称为“语法糖”,用于处理函数值。第一个是这个:

function foo() end

这与以下内容完全相同:
foo = function() end

另一个是:

function bar.foo() end

这完全等同于:

bar.foo = function() end

在这个例子中,bar 是一个表格,foo 是该表格中的一个键,而我们创建的函数值就是分配给该键的值。
请注意,如果您调用 foo
bar.foo()

函数无法知道它是使用键 foo 存储在表 bar 中的,如果你想将该函数作为对象 bar 的一个方法来处理,你需要以某种方式提供访问 bar 的权限。通常可以通过将 bar 作为第一个参数传递来完成。按照 Lua 的习惯,这个参数被命名为 self
function bar.foo(self) end

bar.foo(bar)

作为该约定的一种快捷方式,Lua 通过 : 运算符提供了以下语法糖:

function bar:foo() end

bar:foo()

这与先前的代码完全等效。


上面最后一个代码示例中有一个小错误,应该是 __bar:foo()__(冒号需要让 Lua 自动将 'bar' 作为 'foo' 函数的第一个参数传递)。 - cabbageforall
1
很好的解释。有一个问题:如果我调用 bar:foo(),假设 bar 被隐式传递到方法体中,那么我如何调用 bar?它实际上是 self 吗? - IAbstract
3
是的。function bar:foo() end 直译为 function bar.foo(self) end,因此 foo 无论你是否给它其他参数,都有一个名为 self 的第一个参数。bar:foo() 直译为 bar.foo(bar),所以在 foo 中,self 将包含 bar - Mud

7

当您使用冒号表示法调用函数时,就像这样:

foo:bar()

Lua在幕后的处理方式如下:
foo.bar(foo)

如果您使用点符号定义函数,则必须手动指定“self”参数:

function foo.bar(self) ... end

然而,如果您使用冒号表示法,Lua将会为您添加一个隐藏的“self”参数:
function foo:bar() ... end

即使您看不到self参数,它在幕后存在。

基本上冒号表示法只是一种让您的代码看起来更清洁的方法。

另请参阅:Lua:冒号表示法,self和函数定义与调用


为什么有些函数根本没有foo,而只是用bar?那是什么意思?另外,self是指类的实例吗?我对Lua还很陌生。为什么我需要self? - CodeCamper
如果你有foo.bar()或foo:bar(),那么函数只是'foo'表上的一个属性。函数放在哪里并不重要...它们可以是本地定义的__local function bar() ... end__,全局定义的__function bar() ... end__,或者作为表的属性定义,__function foo.bar() ... end__。__self__不是必需的,除非你需要它。如果你不需要对表或对象的引用,那么你不需要使用冒号符号或self。 - cabbageforall

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