Scala 中的 apply 函数是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9737352/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the apply function in Scala?
提问by Jesvin Jose
I never understood it from the contrived unmarshalling and verbing nouns ( an AddTwoclass has an applythat 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 applyfunction give? What is it used for, and what purposes does it make code better (unmarshalling, verbing nouns etc)?
带有apply函数的类有什么意义?它有什么用途,它使代码更好的用途是什么(解组、动词名词等)?
how does it help when used in a companion object?
在伴生对象中使用时它有什么帮助?
回答by Vlad Gudim
Mathematicians have their own little funny ways, so instead of saying "then we call function fpassing it xas a parameter" as we programmers would say, they talk about "applying function fto its argument x".
数学家有他们自己的一些有趣的方法,所以他们不是像我们程序员所说的那样说“然后我们调用函数f将其x作为参数传递”,而是谈论“将函数f应用于其参数x”。
In mathematics and computer science, Apply is a function that applies functions to arguments.
Wikipedia
在数学和计算机科学中,Apply 是将函数应用于参数的函数。
维基百科
applyserves the purpose of closing the gap between Object-Oriented and Functional paradigms in Scala. Every function in Scala can be represented as an object. Every function also has an OO type: for instance, a function that takes an Intparameter and returns an Intwill have OO type of Function1[Int,Int].
apply用于缩小 Scala 中面向对象范式和函数范式之间的差距。Scala 中的每个函数都可以表示为一个对象。每个函数也有一个 OO 类型:例如,一个接受一个Int参数并返回一个IntOO 类型的函数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 fcan now be treated as a reference to Function1[Int,Int]object. For example, we can call toStringmethod inherited from Any, that would have been impossible for a pure function, because functions don't have methods:
由于 Scala 中的一切都是对象,f现在可以将其视为对Function1[Int,Int]object的引用。例如,我们可以调用toString继承自 的方法Any,这对于纯函数来说是不可能的,因为函数没有方法:
f.toString
Or we could define another Function1[Int,Int]object by calling composemethod on fand chaining two different functions together:
或者我们可以Function1[Int,Int]通过调用compose方法f并将两个不同的函数链接在一起来定义另一个 对象:
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 applymethod on the Function1[Int,Int]object:
现在,如果我们想实际执行该函数,或者如数学家所说的“将函数应用于其参数”,我们将调用对象apply上的方法Function1[Int,Int]:
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). That's where Scala compiler steps in and whenever we have a reference fto 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).
f.apply(args)每次要执行表示为对象的函数时都编写代码是面向对象的方式,但是会在不添加太多附加信息的情况下给代码增加很多混乱,并且能够使用更标准的符号会很好,例如作为f(args)。这就是 Scala 编译器f介入的地方,每当我们引用一个函数对象并写入f (args)将参数应用到所表示的函数时,编译器就会悄悄地扩展f (args)到对象方法 call 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 applymethod. Such objects can be used in the function notation:
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
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 applyobject 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 applymethod is just a handy way of closing the gap between functions and objects in Scala.
因此,apply方法只是缩小 Scala 中函数和对象之间差距的一种便捷方式。
回答by Nicolas
It comes from the idea that you often want to applysomething to an object. The more accurate example is the one of factories. When you have a factory, you want to applyparameter 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. 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:
Scala 人员认为,由于它在许多情况下都会发生,因此有一个调用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.Seqis implemented: Seqis 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)不会编译,但是由于伴随对象和应用,您可以调用Seq(1, 2)并由伴随对象选择实现。
回答by sdinesh94
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
A greeter-2 is being instantiated with message world
输出
一个greeter-1 正在用消息hello 实例化
一个greeter-2正在用消息世界实例化

