鍍金池/ 教程/ Scala/ Sealed Classes
模式的種類(三)
模式限定修飾
簡單的示例
模式的種類(二)
模式無處不在
模式的種類(四)
Sealed Classes
Option 類型
重疊模式定義
模式的種類(一)

Sealed Classes

前面說過,在寫模式匹配時,你必須保證你所寫的可選項覆蓋了全部的可能性,因此常常你必須加上一個缺省通配符選項。但這種情況只適應(yīng)于缺省通配符有意義的情況。如果對于一些沒有缺省項的情況,你怎么才能保證你寫的可選項是完全的呢?

實際上,你可以借助于 Scala 編譯器來幫忙,要做到這一點,編譯器需要預(yù)先知道所有可能的匹配項,這種通常情況下是不可能的。比如你總可以派生出新的子類,然后再可選項中添加這個新創(chuàng)建的子類的模式。

一種可能的實現(xiàn)是為基類添加上 Sealed 關(guān)鍵字,一個 sealed 的類只能在定義它的同一個文件中定義它的子類。這樣你就只需要關(guān)心已經(jīng)定義的子類,如果你使用這些子類做為模式定義,如果可選項不去全的話,編譯器會自動警告。

我們還是使用之前定義的表達式的例子:

    sealed abstract class Expr
    case class Var(name:String) extends Expr
    case class Number(num:Double) extends Expr
    case class UnOp(operator:String, arg:Expr) extends Expr
    case class BinOp(operator:String,left:Expr,right:Expr) extends Expr

下面我們定義一個不完全的模式匹配:

    def describe(e:Expr) :String =e match{
        case Number(_) => "a number"
        case Var(_) => "a variable"
    }

    <console>:12: warning: match may not be exhaustive.
    It would fail on the following inputs: BinOp(_, _, _), UnOp(_, _)
       def describe(e:Expr) :String =e match{
     ^
    describe: (e: Expr)String

編譯器給出警告,表示你的定義可能會拋出 MatchError 異常,因為 BinOp 和 UnOp 沒有定義在模式定義中。

當有的時候,你可能只需要匹配部分模式,一是添加一個缺省匹配,比如通配符模式,例如:

    def describe(e:Expr) :String =e match{
        case Number(_) => "a number"
        case Var(_) => "a variable"
        case _ => throw new RuntimeException
    }

為簡潔起見,Scala 支持使用標注 (annotation) 的方法暫時取消編譯器檢查模式定義是否完備,為變量添加 @unchecked 標注后,編譯器不再給出警告:

    def describe(e:Expr) :String =(e: @unchecked) match{
        case Number(_) => "a number"
        case Var(_) => "a variable"
    }

@unchecked 在模式匹配中具有特殊意義,如果模式匹配的變量使用該標準,Scala 編譯器不對該模式進行完備性檢查。

下一篇:簡單的示例