程式扎記: [Scala 小學堂] Scala Gossic : 繼續深入 - 模式比對 (案例類別)

標籤

2016年7月8日 星期五

[Scala 小學堂] Scala Gossic : 繼續深入 - 模式比對 (案例類別)

Source From Here 
案例類別(Case class) 
在 match 運算式 中看過 match 運算式可以比對數字與字串,實際上,match 可以比對的是模式(Pattern),在正式了解各種模式之前,先來看看所謂的 案例類別Case class),以作為之後模式比對的說明基礎。 

一個案例類別,是在類別定義時加上 case 關鍵字,例如: 
  1. case class Point(x: Int, y: Int)  

對於案例類別,編譯器會對它動些手腳,首先就是編譯器會建立一個以 Point 為名的工廠方法(Factory method),所以你可以這麼建立 Point 的實例,而不用使用 new 來建立: 
  1. val p = Point(12)  
再來就是 Point 參數列上名稱都是 val而不是 private[this] val),所以可以直接存取: 
  1. val p = Point(12)  
  2. println("(" + p.x + ", " + p.y +")")  // 顯示 (1, 2)  
編譯器會為 Point 加上 toStringhashCode 與 equals() 的實作,所以你可以直接顯示 Point 的描述,或者是使用 == 來比較: 
  1. val p1 = Point(12)  
  2. val p2 = Point(12)  
  3. val p3 = Point(21)  
  4. println(p1)       // 顯示 Point(1, 2)  
  5. println(p2)       // 顯示 Point(1, 2)  
  6. println(p3)       // 顯示 Point(2, 1)  
  7. println(p1 == p2) // 顯示 true  
  8. println(p1 == p3) // 顯示 false  
而 案例類別最重要的功能,就是可以作為 match 運算式的 case 比對條件,例如 
  1. def go(p: Point) = p match {  
  2.     case Point(00) => "原點"  
  3.     case Point(1010) => "終點"  
  4.     case _ => "巡迴 " + p  
  5. }  
  6.   
  7. println(go(Point(00)))    // 顯示原點   
  8. println(go(Point(01)))    // 顯示巡迴 Point(0,1)  
  9. println(go(Point(23)))    // 顯示巡迴 Point(2,3)  
  10. println(go(Point(1010)))  // 顯示終點  
在這個例子中,你看到直接比對了傳入的點是否等於 (0, 0)、(10, 10),實際上,這個 match 中運用了 常數模式Constant pattern)、萬用字元模式Wildcard pattern)與 建構式模式Constructor pattern)。 

案例類別運用於模式比對時,也可以形成巢狀,例如: 
  1. case class Point(x: Int, y: Int)  
  2. case class Circle(p: Point, r: Int)  
  3.   
  4. def what(c: Circle) = c match {  
  5.     case Circle(Point(00), _)   => "原點的圓"  
  6.     case Circle(Point(1010), _) => "終點的圓"  
  7.     case _ => "其它的圓"  
  8. }  
  9.   
  10. println(what(Circle(Point(00), 10)))    // 顯示原點的圓  
  11. println(what(Circle(Point(1010), 20)))  // 顯示終點的圓  
  12. println(what(Circle(Point(55), 30)))    // 顯示其它的圓  
在這個例子中,你僅關心傳入的圓是在原點或在終點,而不關心圓半徑為多少,所以在 Circle 的第二個參數部份,設定為 _ 萬用字元,這個例子也是運用了 常數模式萬用字元模式 與 建構式模式。如果你關心半徑,則可以改為以下的方式: 
  1. case class Point(x: Int, y: Int)  
  2. case class Circle(p: Point, r: Int)  
  3.   
  4. def what(c: Circle) = c match {  
  5.     case Circle(Point(00), r)   => "原點的圓, 半徑 " + r  
  6.     case Circle(Point(1010), r) => "終點的圓, 半徑 " + r  
  7.     case Circle(_, r) => "其它的圓, 半徑 " + r  
  8. }  
  9.   
  10. println(what(Circle(Point(00), 10)))    // 顯示原點的圓, 半徑 10  
  11. println(what(Circle(Point(1010), 20)))  // 顯示終點的圓, 半徑 20  
  12. println(what(Circle(Point(55), 30)))    // 顯示其它的圓, 半徑 30  
上面的例子,運用了 常數模式萬用字元模式建構式模式 與 變數模式Variable pattern)。這邊的重點在於了解案例類別運用於 match 運算式的基本方式,模式的種類不只以上所提及的模式,模式之間也可以彼此結合,這將在之後詳加說明。

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!