我从来没有从设计的解组和修饰名词中理解它(一个AddTwo
类apply
增加了两个!)的例子.
我理解它是语法糖,所以(我从上下文推断)它必须被设计为使一些代码更直观.
具有apply
函数的类有什么意义?它用于什么,以及它使代码变得更好的目的(解组,修改名词等)?
在伴侣对象中使用时如何帮助?
Vla*_*dim 616
数学家有他们自己的一些有趣的方式,所以不是说"然后我们称函数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
Run Code Online (Sandbox Code Playgroud)
由于Scala中的所有内容都是对象,f
因此现在可以将其视为Function1[Int,Int]
对象的引用.例如,我们可以调用toString
继承自的方法Any
,这对于纯函数来说是不可能的,因为函数没有方法:
f.toString
Run Code Online (Sandbox Code Playgroud)
或者我们可以Function1[Int,Int]
通过调用compose
方法f
并将两个不同的函数链接在一起来定义另一个 对象:
val f2 = f.compose((x:Int) => x - 1)
Run Code Online (Sandbox Code Playgroud)
现在,如果我们想要实际执行函数,或者数学家说"将函数应用于其参数",我们将apply
在Function1[Int,Int]
对象上调用该方法:
f2.apply(2)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
当我们想要将对象视为函数时,有许多用例.最常见的情况是工厂模式.我们可以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)
Run Code Online (Sandbox Code Playgroud)
因此,apply
方法只是缩小Scala中函数和对象之间差距的一种方便方法.
Nic*_*las 47
它来自于您经常想要将某些东西应用于对象的想法.更准确的例子是工厂之一.如果您有工厂,则需要将参数应用于它以创建对象.
斯卡拉家伙认为,在许多情况下会发生这种情况,因此有一个快捷方式可以调用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)
Run Code Online (Sandbox Code Playgroud)
它通常用在伴侣对象中,为类或特征提供一个很好的工厂方法,这里有一个例子:
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
}
}
Run Code Online (Sandbox Code Playgroud)
从scala标准库中,您可以看一下如何scala.collection.Seq
实现:Seq
是一个特性,因此new Seq(1, 2)
不会编译,但是由于伴随对象和apply,您可以调用Seq(1, 2)
并且伴随对象选择实现.
Tom*_*čka 10
TLDR 适用于来自以下国家/地区的用户c++
它只是( )
括号运算符的重载
所以在斯卡拉:
class X {
def apply(param1: Int, param2: Int, param3: Int) : Int = {
// Do something
}
}
Run Code Online (Sandbox Code Playgroud)
与c++中的相同:
class X {
def apply(param1: Int, param2: Int, param3: Int) : Int = {
// Do something
}
}
Run Code Online (Sandbox Code Playgroud)
对于那些想要快速阅读的人来说,这是一个小例子
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")
}
Run Code Online (Sandbox Code Playgroud)
产量
greeter-1正在使用消息hello进行实例化
greeter-2正在使用消息世界进行实例化
归档时间: |
|
查看次数: |
101656 次 |
最近记录: |