Scala建立新的控制結構
創造新的控制結構——問號表示式 “? :”
Scala的英文意思是“可伸展的”。Scala之所以叫這個名,就是取意這個語言是“可伸展的語言”。他的可伸展性表現在很多方面。今天主要總結一下他在創造新的控制結構方面的能力。
語言內建的控制結構有:for,if...else,while等,在Scala裡,你完全可以寫出自己的控制結構,讓它感覺像是語言本身就支援一樣。先把示例丟擲來——Scala裡沒有Java、C++裡的問號表示式 ? : ,下面我們自己如何來給Scala裡引入這個控制結構,程式碼如下:
object work { implicit class Condition(p: Boolean) { def ?[A] (first: A): Selection[A] = new Selection(p, first) } class Selection[A](p: Boolean, first: A) { def | (second: A): A = p match { case true => first case _ => second } } }
測試一下:
println( (1 > 0) ? "good" | "bad")
// > good
看看 (1 > 0) ? "good" | "bad" 這個語句是怎麼執行的
1. (1 > 0) 返回一個Boolean型別的值
2. 由於Boolean型別沒有名叫 ? 的函式,編譯器會把Boolean值隱式轉換為Condition型別
Condition類被宣告為implicit,這是一個隱式類,他的主建構函式就相當於隱式轉換函式。(注:隱式類的主建構函式只能有一個引數)。編譯器發現一個Boolean型別後面跟著一個 ? 的方法,Boolean型別裡沒有這個方法,他就會在編譯上下文中去找一個可用的隱式轉換。隱式轉換實際上相當於執行了new Condition(1 > 0)。
3. 執行Condition型別的 ? 操作後,返回一個Selection物件
這裡 ? 成員函式的呼叫方法是“中綴操作符標註”的呼叫方法。 在Scala裡沒有運算子的概念,一切都是函式呼叫,比如1 + 2實際上呼叫的Int型別的+方法,其等同於1.+(2)。但是如果只能寫成1.+(2)這樣,非常不優雅,為此,Scala提供這種“中綴操作符標註”的方式:1 + 2。所以,例子中的 (1 > 0) ? "good" 實際上等於與(1 > 0).?("good"),這樣產生了一個Selection物件
4. 執行Selection型別的 | 操作,返回整個問號表示式運算結果值
同上,Selection的 | 也是一個"中綴操作符標註", "bad"是這個方法的入參。(注:由於Scala裡冒號:不能做方法名,所有這裡用|代替)
剝開語法糖衣,還原本來面目
這個例子中的“中綴操作符標註”、隱式轉換等,都是為了使問號表示式“ ? | ”用起來像Scala原生自帶的關鍵字一樣。拋開一層層語法糖衣,他的本來面目是這樣的:
(new Condition( (1 > 0) ).?("good")).|("bad")
總結
這個小例子展現了Scala強大的“可伸展性”——可以建立新的控制結構,擴充套件Scala語言本身。這也是Scala語言迷人之處!
短短几行程式碼,涉及著很多知識:
1. 隱式轉換
2. Scala裡的操作符(中綴操作符)
3. 型別引數