Scala
是一门结合OO
, FP
特性的混血儿,支持多种范式的程序设计语言。本文通过一个简单的例子,开启Scala
的破冰之旅。
需求:将一个字符串序列依次转化为大写
破冰
object Strings {
def upper(strs: String*): Seq[String] = {
strs.map((s: String) => s.toUpperCase())
}
}
单键对象
Scala
摒弃了static
的语义,使用object
,体现了Scala
纯正的OO
血统。诸如静态工厂方法,工具类等实现模式,是Scala
单键对象最佳的使用场景。
变长参数
strs: String*
表示变长的字符串列表,可以向Strings.upper
传递任意多的字符串。事实上,strs: String*
的真正类型为scala.collection.mutable.WrappedArray
,所以strs: String*
拥有普通集合类的一般特征,例如调用map
方法。
泛型
Seq[String]
是Scala
的泛型表示,而非Seq<String>
。Seq
表示一个有序的集合。事实上,strs.map
返回的类型实际为scala.collection.mutable.ArrayBuffer
,但用户无需感知这个事实,这也体现了「按照接口编程」的良好设计原则。
一等函数
(s: String) => s.toUpperCase()
是一个函数字面值,或者将其看成一个匿名函数。事实上,它真正的类型为:Function1[String, String]
,表示入参为String
类型,返回值为String
的一元函数,从而将FP
很优雅地融入到OO
的世界之中。
表达式
Scala
一切都是面向表达式的,包括函数或方法;此外,函数返回值的=
语法,也增强了Scala
类型推演的能力,而且常常略去显式的return
关键字(显式的return
,相反削弱了函数返回值自动推演的能力)。
特殊地,当函数只包含单条语句时,常常略去大括号,使得函数更像表达式,程序因此也变得极其优雅,简单,漂亮。
def upper(strs: String*): Seq[String] =
strs.map((s: String) => s.toUpperCase())
类型推演
事实上,编译器可以很容易地推演出匿名函数的入参类型,函数字面值可以变得更加简单。
def upper(strs: String*): Seq[String] =
strs.map(s => s.toUpperCase())
省略括号
按照惯例,略去s.toUpperCase()
的括号,强调函数是无副作用的。
def upper(strs: String*): Seq[String] =
strs.map(s => s.toUpperCase)
占位符
因为函数字面值s => s.toUpperCase
中的s
在函数体内仅出现一次,可以使用「占位符」进一步简化程序。
def upper(strs: String*): Seq[String] =
strs.map(_.toUpperCase)
重载
-
第二个
upper
重载函数,必须显式地声明返回值类型;不能指望根据第一个重载的upper
函数能够自动推演其返回值类型。 -
strs: _*
是将集合对象展开为变长参数的特殊语法。
object Strings {
def upper(strs: String*): Seq[String] =
strs.map(_.toUpperCase)
def upper(strs: Array[String]): Seq[String] =
upper(strs: String*)
}
网友评论