Scala中的应用函数是什么?

我从来没有从人为的反编组和名词中理解它(一个AddTwo类有一个apply ,增加了两个!)的例子。

我知道它是句法糖,所以(我从上下文中推导出来的)一定是为了让一些代码更直观而devise的。

带有apply函数的类有什么意义? 它的用途是什么,它是什么目的使代码更好(解组,名词等)?

在伴侣对象中使用它有什么帮助?

math家有自己的一些有趣的方法,所以我们不是说程序员会说“那么我们把函数f作为一个parameter passing给它”,而是说“把函数f应用到它的参数x ”。

在math和计算机科学中,Apply是一个将函数应用于参数的函数。
维基百科

apply于缩小Scala中面向对象和function范例之间差距的目的。 Scala中的每个函数都可以表示为一个对象。 每个函数还有一个OOtypes:例如,一个接受一个Int参数并返回一个IntFunction1[Int,Int]将具有OOtypes的Function1[Int,Int]

  // define a function in scala (x:Int) => x + 1 // assign an object representing the function to a variable val f = (x:Int) => x + 1 

由于一切都是Scala中的一个对象,因此现在可以将其视为对Function1[Int,Int]对象的引用。 例如,我们可以调用从Anyinheritance的toString方法,这对纯函数来说是不可能的,因为函数没有方法:

  f.toString 

或者我们可以通过调用f上的compose方法并将两个不同的函数链接在一起来定义另一个Function1[Int,Int]对象:

  val f2 = f.compose((x:Int) => x - 1) 

现在,如果我们想要实际执行函数,或者像math家所说的“将函数应用于其参数”那么我们将在Function1[Int,Int]对象上调用apply方法:

  f2.apply(2) 

每次你想要执行一个表示为一个对象的函数时,编写f.apply(args)就是面向对象的方式,但是会在代码中增加大量的混乱而不增加额外的信息,这样能够使用更多的标准符号,如f(args) 。 这就是Scala编译器的步骤,每当我们有一个函数对象的引用f ,并写入f (args)将参数应用于表示函数时,编译器将f (args)默认扩展到对象方法调用f.apply (args)

Scala中的每个函数都可以作为一个对象来处理,它也可以用另一种方式工作 – 每个对象都可以作为一个函数来处理,只要它具有apply方法。 这些对象可以在函数表示法中使用:

 // we will be able to use this object as a function, as well as an object object Foo { var y = 5 def apply (x: Int) = x + y } Foo (1) // using Foo object in function notation 

当我们想把一个对象作为一个函数的时候,有很多的用例。 最常见的情况是工厂模式 。 我们可以apply对象应用于一组参数来创build关联类的新实例,而不是使用工厂方法将代码添加到代码中:

 List(1,2,3) // same as List.apply(1,2,3) but less clutter, functional notation // the way the factory method invocation would have looked // in other languages with OO notation - needless clutter List.instanceOf(1,2,3) 

所以apply方法只是缩小Scala中函数和对象之间差距的一个方便的方法。

它来自于你经常想要东西应用于某个对象的想法。 更准确的例子是工厂之一。 当你有一个工厂时,你想要应用参数来创build一个对象。

斯卡拉人认为,如果发生在很多情况下,可以有一个快捷方式来调用apply 。 因此,当你给参数直接给一个对象的时候,就像把这些parameter passing给这个对象的apply函数一样:

 class MyAdder(x: Int) { def apply(y: Int) = x + y } val adder = new MyAdder(2) val result = adder(4) // equivalent to x.apply(4) 

它常常用于伴侣对象,为类或特质提供一个漂亮的工厂方法,下面是一个例子:

 trait A { val x: Int def myComplexStrategy: Int } object A { def apply(x: Int): A = new MyA(x) private class MyA(val x: Int) extends A { val myComplexStrategy = 42 } } 

从scala标准库,你可能会看scala.collection.Seq是如何实现的: Seq是一个特征,因此new Seq(1, 2)不会编译,但是由于伴侣对象和apply,你可以调用Seq(1, 2) ,实现是由伴侣对象select的。

对于那些想快速阅读的人来说,这是一个小例子

  object ApplyExample01 extends App { class Greeter1(var message: String) { println("A greeter-1 is being instantiated with message " + message) } class Greeter2 { def apply(message: String) = { println("A greeter-2 is being instantiated with message " + message) } } val g1: Greeter1 = new Greeter1("hello") val g2: Greeter2 = new Greeter2() g2("world") } 

产量

greeter-1正在用消息hello实例化

迎宾2正在与消息世界实例化