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

Jef*_*eff 79 scala syntactic-sugar magic-methods companion-object

在Scala中,如果我定义一个apply在类或顶级对象中调用的方法,那么每当我将一个圆括号添加到该类的实例时,将调用该方法,并apply()在它们之间放置适当的参数.例如:

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

val f = new Foo(3)
f(4)   // returns 25
Run Code Online (Sandbox Code Playgroud)

所以基本上,object(args)只是语法糖object.apply(args).

Scala如何进行此转换?

这里是否存在全局定义的隐式转换,类似于Predef对象中的隐式类型转换(但实物类型不同)?或者它是一些更深层次的魔法?我问,因为看起来Scala强烈赞成一套较小的规则的一致应用,而不是许多例外的许多规则.这最初对我来说似乎是个例外.

oxb*_*kes 66

我认为没有什么比你最初所说的更深入了:它只是语法糖,编译器将其f(a)转换f.apply(a)为特殊的语法案例.

这似乎是一个特定的规则,但只有少数(例如,with update)允许类似DSL的构造和库.

  • 我添加"当`f`是一个对象(包括函数)".当`f`是一种方法时,显然没有这种翻译. (4认同)
  • @AlexeyRomanov:好吧,如果`f`是一个没有参数列表定义的方法,那么`f(a)`确实被解释为`val _tmp = f; _tmp.apply(一)`.但这确实已经牢牢地进入了分裂的领域. (2认同)

seb*_*sgo 20

实际上是另一种方式,带有apply方法的对象或类是正常情况,而函数是使用apply方法隐式构造同名对象的方法.实际上,您定义的每个函数都是Function n trait 的子对象(n是参数的数量).

有关该主题的更多信息,请参阅Scala语言规范第77页的6.6:函数应用程序.


Ale*_*nov 8

我问,因为看起来Scala强烈赞成一套较小的规则的一致应用,而不是许多例外的许多规则.

是.而这个规则属于这个较小的集合.