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*)
}