我从来没有从那些做作的、不加修饰的名词(一个AddTwo类有一个apply加两个!)示例。
我知道这是语法上的甜头,所以(我从上下文推断)它的设计一定是为了让一些代码更直观。
具有apply函数的类给出了什么含义?它的用途是什么?它有什么目的使代码更好(解组、逐字逐句名词等)?
当在伴生对象中使用时,它有什么帮助?
- 即使是快速的谷歌搜索也会带来很多好文章。这里有一个:jackcoughonsoftware.blogspot.com/2009/01/…
- stackoverflow.com/questions/1223834/…
- 实际上,它与爪哇/c++中的构造函数相同,但可以返回值并具有"应用"名称。
- 这是一个方法,而不是一个函数。方法和函数之间的区别在scala中非常重要。
- 要详细介绍Zoidberg,"方法只是可以访问类状态的函数"twitter.github.io/scala_school/basics.html一般来说,这适用于scala stackoverflow.com/questions/155609/…
数学家们有他们自己的一些有趣的方式,因此他们没有像我们的程序员所说的那样说"然后我们称函数f传递它x作为参数",而是说"将函数f应用到它的参数x"。
In mathematics and computer science, Apply is a function that applies
functions to arguments.
Wikipedia
号
apply的作用是缩小scala中面向对象范式和功能范式之间的差距。scala中的每个函数都可以表示为一个对象。每个函数也都有一个OO类型:例如,一个接受Int参数并返回Int的函数将有一个Function1[Int,Int]的OO类型。
1 2 3 4 5
| // 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]对象的引用。例如,我们可以调用从Any继承的toString方法,这对于纯函数来说是不可能的,因为函数没有方法:
。
或者我们可以通过调用f上的compose方法并将两个不同的函数链接在一起来定义另一个Function1[Int,Int]对象:
1
| val f2 = f. compose((x :Int ) => x - 1) |
现在,如果我们要实际执行函数,或者像数学家所说的"将函数应用于其参数",我们将在Function1[Int,Int]对象上调用apply方法:
。
每次要执行一个表示为对象的函数时,编写f.apply(args)都是面向对象的方法,但是如果不添加太多附加信息,就会给代码增加很多混乱,而且能够使用更多的标准符号(如f(args))也会很好。这就是scala编译器介入的地方,每当我们引用f到一个函数对象,并编写f (args)来将参数应用到表示的函数时,编译器就会悄悄地将f (args)扩展到对象方法调用f.apply (args)。
scala中的每一个函数都可以作为一个对象来处理,它也可以以另一种方式工作——只要每个对象具有apply方法,就可以作为一个函数来处理。这些对象可以在函数符号中使用:
1 2 3 4 5 6 7 8
| // 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 |
。
当我们希望将对象视为函数时,有许多使用案例。最常见的场景是工厂模式。我们不必使用工厂方法向代码中添加混乱,而是可以将cx1〔0〕对象添加到一组参数中,以创建关联类的新实例:
1 2 3 4 5
| 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?
- scala中的类型通常可以根据参数推断,但如果不是,则可以通过方括号提供。因此,当实例化一个平均对象时,您可以说"val avg=new average[int](0)"。
- 案例类在这里值得一提。case类方便、自动、无形地将apply和unapply方法添加到类的一个伴生对象中(除其他外)。因此,用这样的一条线定义一个类(EDOCX1)(3),就可以通过val myCar = Car("VW","Golf",1999,"Blue")生成汽车类的新对象。这是Car.apply(...)的简写。
- every object can be treated as a function, provided it has the apply method—现在这么多都有意义了。
- list.instanceof(1,2,3)给出了一个错误i注
它来自于这样一个想法,即你经常想把一些东西应用到一个对象上。更准确的例子是一家工厂。当您有一个工厂时,您需要对它应用参数来创建一个对象。
scala的人认为,在很多情况下,有一个快捷方式调用apply可能会更好。因此,当您直接向一个对象提供参数时,它会被丢弃,就像您将这些参数传递给该对象的apply函数一样:
1 2 3 4 5 6
| class MyAdder (x : Int ) {
def apply (y : Int ) = x + y
}
val adder = new MyAdder (2)
val result = adder (4) // equivalent to x.apply(4) |
它通常用于伴生对象中,为类或特性提供一个好的工厂方法,下面是一个示例:
号
从scala标准库中,您可以看到scala.collection.Seq是如何实现的:Seq是一个特性,因此new Seq(1, 2)不会编译,但由于伴随对象和应用,您可以调用Seq(1, 2),实现是由伴随对象选择的。
- 是否也可以使用implicits来实现等效的apply?
下面是一个小例子,给那些想快速阅读的人
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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
号
- G2的信息是否正确?这是在实例化时发生的,还是在实例化之后发生的(即使它是懒惰地实例化的)?