在 match 運算式 中看過match運算式可以比對數字與字串,實際上,match可以比對的是模式(Pattern),在正式了解各種模式之前,先來看看所謂的案例類別(Case class),以作為之後模式比對的說明基礎。
一個案例類別,是在類別定義時加上case關鍵字,例如:
case class Point(x: Int, y: Int)
對於案例類別,編譯器會對它動些手腳,首先就是編譯器會建立一個以Point為名的工廠方法(Factory method),所以你可以這麼建立Point的實例,而不用使用new來建立:
val p = Point(1, 2)
再來就是Point參數列上名稱都是val(而不是private[this] val),所以可以直接存取:
val p = Point(1, 2)
println("(" + p.x + ", " + p.y +")") // 顯示 (1, 2)
編譯器會為Point加上toString、hashCode與equals()的實作,所以你可以直接顯示Point的描述,或者是使用==來比較:
val p1 = Point(1, 2)
val p2 = Point(1, 2)
val p3 = Point(2, 1)
println(p1) // 顯示 Point(1, 2)
println(p2) // 顯示 Point(1, 2)
println(p3) // 顯示 Point(2, 1)
println(p1 == p2) // 顯示 true
println(p1 == p3) // 顯示 false
而案例類別最重要的功能,就是可以作為match運算式的case比對條件,例如:
def go(p: Point) = p match {
case Point(0, 0) => "原點"
case Point(10, 10) => "終點"
case _ => "巡迴 " + p
}
println(go(Point(0, 0))) // 顯示原點
println(go(Point(0, 1))) // 顯示巡迴 Point(0,1)
println(go(Point(2, 3))) // 顯示巡迴 Point(2,3)
println(go(Point(10, 10))) // 顯示終點
在這個例子中,你看到直接比對了傳入的點是否等於(0, 0)、(10, 10),實際上,這個match中運用了常數模式(Constant pattern)、萬用字元模式(Wildcard pattern)與建構式模式(Constructor pattern)。
案例類別運用於模式比對時,也可以形成巢狀,例如:
case class Point(x: Int, y: Int)
case class Circle(p: Point, r: Int)
def what(c: Circle) = c match {
case Circle(Point(0, 0), _) => "原點的圓"
case Circle(Point(10, 10), _) => "終點的圓"
case _ => "其它的圓"
}
println(what(Circle(Point(0, 0), 10))) // 顯示原點的圓
println(what(Circle(Point(10, 10), 20))) // 顯示終點的圓
println(what(Circle(Point(5, 5), 30))) // 顯示其它的圓
在這個例子中,你僅關心傳入的圓是在原點或在終點,而不關心圓半徑為多少,所以在Circle的第二個參數部份,設定為_萬用字元,這個例子也是運用了常數模式、萬用字元模式與建構式模式。如果你關心半徑,則可以改為以下的方式:
case class Point(x: Int, y: Int)
case class Circle(p: Point, r: Int)
def what(c: Circle) = c match {
case Circle(Point(0, 0), r) => "原點的圓, 半徑 " + r
case Circle(Point(10, 10), r) => "終點的圓, 半徑 " + r
case Circle(_, r) => "其它的圓, 半徑 " + r
}
println(what(Circle(Point(0, 0), 10))) // 顯示原點的圓, 半徑 10
println(what(Circle(Point(10, 10), 20))) // 顯示終點的圓, 半徑 20
println(what(Circle(Point(5, 5), 30))) // 顯示其它的圓, 半徑 30
上面的例子,運用了常數模式、萬用字元模式、建構式模式與變數模式(Variable pattern)。
這邊的重點在於了解案例類別運用於match運算式的基本方式,模式的種類不只以上所提及的模式,模式之間也可以彼此結合,這將在之後詳加說明。