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