Source From Here
密封類別(Sealed class)
如果你寫了以下的 案例類別:
若你想寫個函式進行模式比對,對於傳入的物件看看是不是點、圓或柱的一種:
也許你的案例類別較多,或者是你一時寫錯了,少寫了其中幾個案例 (
如 Circle), 程式可以如常編譯,但若你傳入了個 Circle,則會發生 scala.MatchError。對於在進行模式比對時,一定要出現的案例類型,可以將之 密封(Sealed),例如:
你使用
sealed 關鍵字修飾類別,則繼承該類別的子類別,必須與該父類別位於同一個原始碼中,你也可以使用 sealed 修飾特徵(Trait),例如:
如果你如之前,少寫了其中一個案例:
則編譯器會提出警示訊息:
編譯器在告訴你,有些模式的類型你沒有列在 match 運算式的案例串(Case sequence)之中。你必須每個都列出來才可以. 有時候,你使用別人密封過的案例類別,但也許你真的只想比對其中幾個案例類型,如果不想要編譯器惱人的警示訊息,則可以在最後使用萬用字元模式,例如:
如果真的不想要使用萬用字元作額外處理,那麼也可以使用
@unchecked 標註(Annotation)來告訴編譯器住嘴:
如果你寫了以下的 案例類別:
- case class Point(x: Int, y: Int)
- case class Circle(p: Point, r: Int)
- case class Cylinder(c: Circle, h: Int)
- def what(a: Any) = a match {
- case Point(_, _) => "點"
- case Circle(_, _) => "圓"
- case Cylinder(_, _) => "柱"
- }
- sealed abstract class Drawing
- case class Point(x: Int, y: Int) extends Drawing
- case class Circle(p: Point, r: Int) extends Drawing
- case class Cylinder(c: Circle, h: Int) extends Drawing
- sealed trait Drawing
- case class Point(x: Int, y: Int) extends Drawing
- case class Circle(p: Point, r: Int) extends Drawing
- case class Cylinder(c: Circle, h: Int) extends Drawing
- def what(d: Drawing) = d match {
- case Point(_, _) => "點"
- case Cylinder(_, _) => "柱"
- }
編譯器在告訴你,有些模式的類型你沒有列在 match 運算式的案例串(Case sequence)之中。你必須每個都列出來才可以. 有時候,你使用別人密封過的案例類別,但也許你真的只想比對其中幾個案例類型,如果不想要編譯器惱人的警示訊息,則可以在最後使用萬用字元模式,例如:
- def what(d: Drawing) = d match {
- case Point(_, _) => "點"
- case Cylinder(_, _) => "柱"
- case _ => "" // 作你想作的事,或者丟出例外
- }
- sealed trait Drawing
- case class Point(x: Int, y: Int) extends Drawing
- case class Circle(p: Point, r: Int) extends Drawing
- case class Cylinder(c: Circle, h: Int) extends Drawing
- def what(d: Drawing) = (d: @unchecked) match {
- case Point(_, _) => "點"
- case Cylinder(_, _) => "柱"
- }
- val p = Point(1, 2)
- val c = Circle(p, 5)
- val cy = Cylinder(c, 10)
- println(what(p)) // 點
- // println(what(c)) // Will throws scala.MatchError
- println(what(cy)) // 柱
沒有留言:
張貼留言