本文翻译自:What is the apply function in Scala?
I never understood it from the contrived unmarshalling and verbing nouns ( an AddTwo
class has an apply
that adds two!) examples. 我从来没有从设计的解组和修改名词中理解它(一个AddTwo
类有一个apply
,它增加了两个!)的例子。
I understand that it's syntactic sugar, so (I deduced from context) it must have been designed to make some code more intuitive. 我理解它是语法糖,所以(我从上下文推断)它必须被设计为使一些代码更直观。
What meaning does a class with an apply
function give? 具有apply
函数的类有什么意义? What is it used for, and what purposes does it make code better (unmarshalling, verbing nouns etc)? 它用于什么,以及它使代码变得更好的目的(解组,修改名词等)?
how does it help when used in a companion object? 在伴侣对象中使用时如何帮助?
#1楼
参考:https://stackoom.com/question/ER84/Scala中的apply函数是什么
#2楼
Here is a small example for those who want to peruse quickly 对于那些想要快速阅读的人来说,这是一个小例子
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")
}
output 产量
A greeter-1 is being instantiated with message hello greeter-1正在使用消息hello进行实例化
A greeter-2 is being instantiated with message world greeter-2正在使用消息世界进行实例化
#3楼
It comes from the idea that you often want to apply something to an object. 它来自于您经常想要将某些东西应用于对象的想法。 The more accurate example is the one of factories. 更准确的例子是工厂之一。 When you have a factory, you want to apply parameter to it to create an object. 如果您有工厂,则需要将参数应用于它以创建对象。
Scala guys thought that, as it occurs in many situation, it could be nice to have a shortcut to call apply
. Scala家伙认为,在很多情况下都会出现这种情况,因此有一个快捷方式可以调用apply
。 Thus when you give parameters directly to an object, it's desugared as if you pass these parameters to the apply function of that object: 因此,当您直接向对象提供参数时,它就像将这些参数传递给该对象的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)
It's often use in companion object, to provide a nice factory method for a class or a trait, here is an example: 它通常用在伴侣对象中,为类或特征提供一个很好的工厂方法,这里有一个例子:
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
}
}
From the scala standard library, you might look at how scala.collection.Seq
is implemented: Seq
is a trait, thus new Seq(1, 2)
won't compile but thanks to companion object and apply, you can call Seq(1, 2)
and the implementation is chosen by the companion object. 从scala标准库中,您可以看看scala.collection.Seq
是如何实现的: Seq
是一个特征,因此new Seq(1, 2)
将无法编译,但是由于伴随对象和apply,您可以调用Seq(1, 2)
并且实现由伴随对象选择。
#4楼
Mathematicians have their own little funny ways, so instead of saying "then we call function f
passing it x
as a parameter" as we programmers would say, they talk about "applying function f
to its argument x
". 数学家有他们自己的一些有趣的方式,所以不是说“然后我们称函数f
将x
作为参数传递”,正如我们程序员所说,他们谈论“将函数f
应用于其参数x
”。
In mathematics and computer science, Apply is a function that applies functions to arguments. 在数学和计算机科学中,Apply是一个将函数应用于参数的函数。
Wikipedia 维基百科
apply
serves the purpose of closing the gap between Object-Oriented and Functional paradigms in Scala. apply
用于缩小Scala中面向对象和功能范例之间的差距。 Every function in Scala can be represented as an object. Scala中的每个函数都可以表示为一个对象。 Every function also has an OO type: for instance, a function that takes an Int
parameter and returns an Int
will have OO type of Function1[Int,Int]
. 每个函数也有一个OO类型:例如,一个接受Int
参数并返回一个Int
的Function1[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
Since everything is an object in Scala f
can now be treated as a reference to Function1[Int,Int]
object. 因为一切是Scala对象f
现在可以作为一个参考被处理Function1[Int,Int]
对象。 For example, we can call toString
method inherited from Any
, that would have been impossible for a pure function, because functions don't have methods: 例如,我们可以调用从Any
继承的toString
方法,这对于纯函数来说是不可能的,因为函数没有方法:
f.toString
Or we could define another Function1[Int,Int]
object by calling compose
method on f
and chaining two different functions together: 或者我们可以通过在f
上调用compose
方法并将两个不同的函数链接在一起来定义另一个Function1[Int,Int]
对象:
val f2 = f.compose((x:Int) => x - 1)
Now if we want to actually execute the function, or as mathematician say "apply a function to its arguments" we would call the apply
method on the Function1[Int,Int]
object: 现在,如果我们想要实际执行该函数,或者数学家说“将函数应用于其参数”,我们将在Function1[Int,Int]
对象上调用apply
方法:
f2.apply(2)
Writing f.apply(args)
every time you want to execute a function represented as an object is the Object-Oriented way, but would add a lot of clutter to the code without adding much additional information and it would be nice to be able to use more standard notation, such as f(args)
. 每次要执行表示为对象的函数时,编写f.apply(args)
都是面向对象的方式,但是会在不添加太多额外信息的情况下给代码添加很多混乱,并且很高兴能够使用更标准的表示法,例如f(args)
。 That's where Scala compiler steps in and whenever we have a reference f
to a function object and write f (args)
to apply arguments to the represented function the compiler silently expands f (args)
to the object method call f.apply (args)
. 这就是Scala编译器进入的地方,每当我们对函数对象有一个引用f
并写入f (args)
以将参数应用于表示的函数时,编译器会静默地将f (args)
扩展为对象方法调用f.apply (args)
。
Every function in Scala can be treated as an object and it works the other way too - every object can be treated as a function, provided it has the apply
method. Scala中的每个函数都可以被视为一个对象,它也可以用另一个方式工作 - 只要它具有apply
方法,每个对象都可以被视为一个函数。 Such objects can be used in the function notation: 这些对象可用于函数表示法:
// 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
There are many usage cases when we would want to treat an object as a function. 当我们想要将对象视为函数时,有许多用例。 The most common scenario is a factory pattern . 最常见的情况是工厂模式 。 Instead of adding clutter to the code using a factory method we can apply
object to a set of arguments to create a new instance of an associated class: 我们可以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)
So apply
method is just a handy way of closing the gap between functions and objects in Scala. 因此, apply
方法只是缩小Scala中函数和对象之间差距的一种方便方法。