Partial application 和 Currying
和大部分函数式语言一样,Scala也支持partial application和currying。在应用函数时,你可以只提供部分的实际参数,而另外一部分参数则使用_
来代替,这样会得到另外一个函数。_
实际上起到一个匿名通配符 (unnamed wildcard) 的作用。
|
|
而Currying则是说一个函数能够接受多个函数参数列表。从本质上,这样的函数可以通过使一个函数将另外一个函数作为返回值来实现。以下面为例,最外层的函数sum
接受一个函数作为参数,并返回sumInternal
作为结果。而在sumInternal
的实现是依赖于sum
的函数参数的。实际调用sum
时的例子为sum((x: Int) => x * x)(0, 2)
|
|
按照这个的模式,我们可以用过嵌套定义函数来实现任意多的函数列表,只是略显繁琐。Scala提供了语法糖来简化Currying函数的定义。
|
|
Partial application和Curring也是可以混合使用的。在multiplyTwoSum
里我们对productSum
两个参数列表都只传入了部分参数,而且得到的结果是(Double, Double) => Double
,即是一个接受两个Double
类型参数的函数。注意这和oneMultiplySum
的区别:oneMultiplySum
接受一个Int
类型的参数,并返回一个(Double, Double) => Double
</code>的函数作为结果。使用Partial application和Curring时,必须仔细观察得到的函数签名。我们也可以对一个partially applied的函数使用
curried`方法,得到它的curried版本。
|
|
变长参数 (Variable length parameters)
Scala支持某个类型的变长参数,只要在函数参数的类型后面加上*
就可以了。变长参数的类型是Seq[T]
,因此大部分数据结构都能作为实际参数传入这样的函数中。
|
|
类 (Classes)
和Java或者C#不同,Scala里类的构造函数 (constructor) 并不是一个专门的方法 (所以构造函数这个翻译对于Scala的语境来说还挺不合适的,构造器可能更加适合一点?),而是指类定义里面除去方法定义 (method definitions) 的所有部分。
|
|
抽象类,继承和重载都很正常。对于抽象类里只声明但是没有实现的定义,在实现时直接定义就可以。如果在抽象类里已经实现了的定义,那在子类里重新实现时要求使用override
关键字。
|
|
Traits
Traits定义了一系列的数据和方法,并且可以用来扩展或者mixin在你的类定义中。Traits和抽象类的特点和使用范围都有很相似的地方,所以选择的时候需要考虑它们不同的特点。一个类能够扩展多个traits,但是只能扩展一个父类。而traits并不能接受构造参数,而抽象类可以。
|
|
类型参数
定义类,函数,和traits时,都可以通过方括号[]
引入类型参数。
|
|
apply 方法
Scala可以让你为类或者对象定义apply
方法,来重载()
运算符。
|
|
Scala里面类和对象能够使用同一个名称。所以通常我们会为一个类定义一个同名的对象 (companion object),作为该类型的factories。
|
|
函数即对象
Scala里面的函数其实是一系列traits的集合。以一个Int => Int
类型的函数为例,它扩展了Function1[Int, Int]
这个trait。而且这个trait定义了apply
函数,因为你可以用调用函数的语法来使用这个对象。实际上,Scala的提供了语法糖,让用户可以用Int => Int
来表示Function1[Int, Int]
。
注意这里的函数并不包括类里面定义的方法。
|
|
EOF