Scala的apply()方法魔术如何工作?


79

在Scala中,如果定义了apply在类或顶级对象中调用的方法,则每当我在该类的实例后面加上一对括号并apply()在它们之间放置适当的参数时,就会调用该方法。例如:

class Foo(x: Int) {
    def apply(y: Int) = {
        x*x + y*y
    }
}

val f = new Foo(3)
f(4)   // returns 25

因此,基本上,object(args)只是的语法糖object.apply(args)

Scala如何进行这种转换?

是否存在全局定义的隐式转换,类似于Predef对象中的隐式类型转换(但种类不同)?还是更深层的魔力?我问,是因为Scala似乎强烈赞成一致地应用较小的规则集,而不是许多例外的规则。最初,这对我来说似乎是个例外。


Answers:


67

我认为没有比您最初说的要深的事情了:这只是语法糖,编译器将其f(a)转换f.apply(a)为特殊的语法情况。

这似乎是一条特定的规则,但是其中只有少数(例如with update)允许使用类似DSL的结构和库。


4
我要添加“何时f是对象(包括函数)”。当f是一种方法时,显然没有这种翻译。
Alexey Romanov

2
@AlexeyRomanov:好吧,如果f定义的方法没有参数列表,那么f(a)确实可以解释为val _tmp = f; _tmp.apply(a)。但这确实已经进入了分裂的领域。
约尔格W¯¯米塔格

20

实际上是相反的情况,使用apply方法的对象或类是正常情况,而函数则是使用apply方法隐式构造同名对象的方法。实际上,您定义的每个函数都是Function的子对象 n特性(n是参数的数量)。

请参见6.6:功能应用的的斯卡拉语言规范为主题的更多信息。


+1用于更改Scala语言规范。由于您的页码已过时,因此我添加了正确的位置。
亚历山大·马丁斯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.