Scala
是一門結(jié)合OO
, FP
特性的混血兒,支持多種范式的程序設(shè)計語言。本文通過一個簡單的例子,開啟Scala
的破冰之旅。
需求:將一個字符串序列依次轉(zhuǎn)化為大寫
破冰
object Strings {
def upper(strs: String*): Seq[String] = {
strs.map((s: String) => s.toUpperCase())
}
}
單鍵對象
Scala
摒棄了static
的語義,使用object
,體現(xiàn)了Scala
純正的OO
血統(tǒng)。諸如靜態(tài)工廠方法,工具類等實現(xiàn)模式,是Scala
單鍵對象最佳的使用場景。
變長參數(shù)
strs: String*
表示變長的字符串列表,可以向Strings.upper
傳遞任意多的字符串。事實上,strs: String*
的真正類型為scala.collection.mutable.WrappedArray
,所以strs: String*
擁有普通集合類的一般特征,例如調(diào)用map
方法。
泛型
Seq[String]
是Scala
的泛型表示,而非Seq<String>
。Seq
表示一個有序的集合。事實上,strs.map
返回的類型實際為scala.collection.mutable.ArrayBuffer
,但用戶無需感知這個事實,這也體現(xiàn)了「按照接口編程」的良好設(shè)計原則。
一等函數(shù)
(s: String) => s.toUpperCase()
是一個函數(shù)字面值,或者將其看成一個匿名函數(shù)。事實上,它真正的類型為:Function1[String, String]
,表示入?yún)?code>String類型,返回值為String
的一元函數(shù),從而將FP
很優(yōu)雅地融入到OO
的世界之中。
表達(dá)式
Scala
一切都是面向表達(dá)式的,包括函數(shù)或方法;此外,函數(shù)返回值的=
語法,也增強了Scala
類型推演的能力,而且常常略去顯式的return
關(guān)鍵字(顯式的return
,相反削弱了函數(shù)返回值自動推演的能力)。
特殊地,當(dāng)函數(shù)只包含單條語句時,常常略去大括號,使得函數(shù)更像表達(dá)式,程序因此也變得極其優(yōu)雅,簡單,漂亮。
def upper(strs: String*): Seq[String] =
strs.map((s: String) => s.toUpperCase())
類型推演
事實上,編譯器可以很容易地推演出匿名函數(shù)的入?yún)㈩愋停瘮?shù)字面值可以變得更加簡單。
def upper(strs: String*): Seq[String] =
strs.map(s => s.toUpperCase())
省略括號
按照慣例,略去s.toUpperCase()
的括號,強調(diào)函數(shù)是無副作用的。
def upper(strs: String*): Seq[String] =
strs.map(s => s.toUpperCase)
占位符
因為函數(shù)字面值s => s.toUpperCase
中的s
在函數(shù)體內(nèi)僅出現(xiàn)一次,可以使用「占位符」進(jìn)一步簡化程序。
def upper(strs: String*): Seq[String] =
strs.map(_.toUpperCase)
重載
第二個
upper
重載函數(shù),必須顯式地聲明返回值類型;不能指望根據(jù)第一個重載的upper
函數(shù)能夠自動推演其返回值類型。strs: _*
是將集合對象展開為變長參數(shù)的特殊語法。
object Strings {
def upper(strs: String*): Seq[String] =
strs.map(_.toUpperCase)
def upper(strs: Array[String]): Seq[String] =
upper(strs: String*)
}