冒号用于方法调用

lua-users home
wiki

在 Lua 中,实例方法的调用通常使用冒号“:”,而访问类/工厂方法或字段则使用点号“.”。

o:test()  -- method call. equivalent to o.test(o)
o.test()  -- regular function call. similar to just test()
o.x = 5   -- field access

关于此行为的详细讨论可在 PIL [1] 中找到。

这两种表示法与其他许多编程语言(包括其他基于原型的语言,如 JavaScript?)不同,后者只使用点号。

// JavaScript example
function print() { WScript.echo("value:" + this.x); }
  
// constructor
function Test() {
  this.x = 5;
  this.print = print;
}
 
t = new Test();
 
print();    // call as function
t.print();  // call as method
t2 = t.print
t2();       // call as function
 
// outputs:
// value:undefined
// value:5
// value:undefined

Rici 指出,JavaScript? 中为了实现这种功能,背后有大量的“魔法”。在 JavaScript? 中错误预测“this”的指向,可能是第二或第三常见 bug。

可以说,访问字段和执行方法调用在语义上是不同的,这值得 Lua 在表示法上加以区分。调用方法就像是将消息**发送给**一个对象。

有关使用闭包以便方法调用可以使用“.”语法的示例,请参阅 PIL [2]。创建大量此类闭包可能效率不高。更多信息请参见 ObjectBenchmarkTests

也许这也可以通过 setfenv 来实现。无论如何,Lua 只有一个类型的表索引操作(“.”),而“:”仅仅是语法糖,这是一个特性。与 JavaScript? 不同,Lua 拥有强大的元机制,可以在语言内部使用;多个表访问操作会显著地使这些机制复杂化。此外,将 Lua 描述为“基于原型的语言”是不准确的。Lua 开箱即用没有对象模型。你可以实现一个原型或经典对象模型。--John Belmonte

IMO,“:”有其存在的价值。如果我不想总是将表作为第一个参数传递,我该如何调用存储在表中的函数?如果你这样做,函数中的隐式 *self* 或 *this* 参数是很自然的下一步。等等,我们不是将所有函数都存储在表中吗,比如 e._G?我宁愿 Lua 不会走上“对象痴迷”的道路……--Frank Hirsch

另请参阅 [__methindex] 提案,该提案使用不同的元方法来区分“:”和“.”。它可以依赖于这样一个事实,即尽管“:”是“.”的语法糖,但它们会产生不同的虚拟机操作码(前者生成 SELF 操作码)。


RecentChanges · preferences
编辑 · 历史
最后编辑于 2010 年 6 月 19 日下午 3:43 GMT (diff)