之间的区别.并且:在Lua

Jas*_*n S 160 lua function

我对函数调用via .和via 之间的区别感到困惑:

> x = {foo = function(a,b) return a end, bar = function(a,b) return b end, }
> return x.foo(3,4)
3
> return x.bar(3,4)
4
> return x:foo(3,4)
table: 0x10a120
> return x:bar(3,4)
3
Run Code Online (Sandbox Code Playgroud)

什么是:做什么?

BMi*_*tch 218

冒号用于实现self作为第一个参数传递的方法.所以x:bar(3,4)应该是一样的x.bar(x,3,4).

  • 啊...所以它是面向对象的语法糖. (49认同)
  • 究竟.在整个参考手册中,他们给出的唯一模糊是"冒号语法用于定义方法,即具有隐式额外参数self的函数." (5.0手册,pdf第19页底部) (7认同)
  • 如果您调用的对象不是本地对象,则@keyle Colon语法会快一些,因为虚拟机只检索一次.基本上像`object.method(object,args)`这样的点语法会两次检索`object`,而`object:method(arg)`只检索`object`一次.如果`object`是全局,upvalue或表字段,则`:`比`.`快.`.`永远不会比`:`快. (7认同)
  • 是否有任何性能成本:vs.? (3认同)
  • 哦啊......我打算问官方文件在哪里,但你打败了我.做得很好.:-) (2认同)

Ole*_*kov 26

对于定义,它与手动指定self 完全相同 - 它甚至会在编译时生成相同的字节码.即function object:method(arg1, arg2)是一样的function object.method(object, arg1, arg2).

关于使用:几乎一样的.-一种特殊的调用将在内部使用,以确保object的计算/接入和任何可能的副作用是只有一次计算.呼叫object:method(arg1, arg2)与否则相同object.method(object, arg1, arg2).


Dar*_*yer 19

完全准确,obj:method(1, 2, 3)是一样的

do
  local _obj = obj
  _obj.method(_obj, 1, 2, 3)
end
Run Code Online (Sandbox Code Playgroud)

为什么是局部变量?因为,正如许多人所指出的那样,obj:method()只有索引_ENV才能获得obj.这在考虑速度时通常很重要,但请考虑以下情况:

local tab do
  local obj_local = { method = function(self, n) print n end }
  tab = setmetatable({}, {__index = function(idx)
    print "Accessing "..idx
    if idx=="obj" then return obj_local end
  end})
end
tab.obj.method(tab.obj, 20)
--> Accessing obj
--> Accessing obj
--> 20
tab.obj:method(10)
--> Accessing obj
--> 10
Run Code Online (Sandbox Code Playgroud)

现在想象一下,__indexmetamethod不仅仅是打印一些东西.想象一下,它增加了一个计数器,将某些内容记录到文件中或从数据库中删除了一个随机用户.这样做两次或只有一次有很大的不同.在这种情况下,obj.method(obj, etc)和之间有明显的区别obj:method(etc).

  • 你真的不应该担心这些事情。如果必须这样做,那么您的架构就存在**严重**的错误。 (2认同)
  • 我会说是相反的方式。好的代码不应对无关代码的实现细节做任何假设。函数调用可能被记住,也可能未被记住,这并不意味着多次调用它们是一种好习惯。 (2认同)