我从未从人为设计的编组和动词名词(一个AddTwo
类有一个apply
添加两个!)的例子中理解了它。
我知道它是语法糖,因此(我从上下文推论得出)它必须经过精心设计,以使某些代码更直观。
具有apply
函数的类给出什么意思?它的作用是什么,它的目的是使代码变得更好(解组,动词名词等)?
在同伴对象中使用时有什么帮助?
我从未从人为设计的编组和动词名词(一个AddTwo
类有一个apply
添加两个!)的例子中理解了它。
我知道它是语法糖,因此(我从上下文推论得出)它必须经过精心设计,以使某些代码更直观。
具有apply
函数的类给出什么意思?它的作用是什么,它的目的是使代码变得更好(解组,动词名词等)?
在同伴对象中使用时有什么帮助?
Answers:
数学家们有他们自己的小滑稽的方式,因此,他们谈论的是“将函数应用于其参数” ,而不是像程序员那样说“然后我们将函数作为参数f
传递给函数”。x
f
x
在数学和计算机科学中,Apply是将函数应用于参数的函数。
维基百科
apply
旨在缩小Scala中的面向对象和功能范式之间的差距。Scala中的每个函数都可以表示为一个对象。每个函数还具有OO类型:例如,一个具有Int
参数并返回的函数Int
将具有OO类型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中的对象,f
现在可以将其视为对Function1[Int,Int]
对象的引用。例如,我们可以调用toString
从继承的方法Any
,对于纯函数来说这是不可能的,因为函数没有方法:
f.toString
或者我们可以Function1[Int,Int]
通过调用compose
on方法f
并将两个不同的函数链接在一起来定义另一个 对象:
val f2 = f.compose((x:Int) => x - 1)
现在,如果我们要实际执行函数,或者如数学家所说的“将函数应用于其参数”,我们将apply
在Function1[Int,Int]
对象上调用该方法:
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
使用一组自变量来创建关联类的新实例,而不是使用工厂方法在代码中添加混乱:
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中函数和对象之间差距的一种便捷方法。
class Average[YType](yZeroValue:YType)
。由于对象不能接受类型参数,如何从其对象传递YType?
apply
和unapply
方法(以及其他方法)。因此,只用这样的一行定义一个类,就case class Car(make:String, model: String, year: Short, color: String)
可以通过just:产生Car类的新对象val myCar = Car("VW","Golf",1999,"Blue")
。这是速记Car.apply(...)
every object can be treated as a function, provided it has the apply method
-现在有很多道理。
它来自您经常想对对象应用某些东西的想法。比较准确的例子是工厂之一。有工厂时,您想对其应用参数以创建对象。
斯卡拉(Scala)的人认为,在许多情况下都会出现这种情况,最好有一个快捷方式来打电话apply
。因此,当您直接将参数提供给对象时,就好像您将这些参数传递给该对象的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)
无法编译,但是由于有了伴随对象并应用,您可以调用Seq(1, 2)
并由伴随对象选择实现。
对于那些想快速阅读的人来说,这是一个小例子
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实例化
greeter-2正在用消息世界实例化