scala case class


在我們詳細介紹Scala的Case class和模式匹配之前,我們可以通過一個簡單的例子來說明一些基本概念。我們設計一個函數庫,這個函數庫可以用來計算算術表達式,為簡單起見,我們設計的算術表達式只側重於變量,數字,單操作符,和雙操作符。我們可以采用如下的Scala類定義:

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

這里我們定義了一個抽象類Expr和四個子類(分別代表變量,數值,單操作符,雙操作符),Scala允許我們不定義類的實現,實際我們是class C 和 class C {}是等價的。

case classes 
我們可以看到上面的四個子類定義前面我們使用了case關鍵字,使用了case關鍵字的類定義就是case classes。使用這個關鍵字,Scala編譯器會自動為你定義的類生成一些成員。 
首先,編譯器為case class生成一個同名的對象構造器(Factory Method),也就是你可以使用 Var(“x”) 來創建一個類的實例,而無需使用new Var(“x”).

scala> val x = Var("x") x: Var = Var(x)

這個構造器在嵌套使用時顯得非常簡潔明了,比如 我們構建如下的表達式,這種寫法避免了很多new 的使用。

scala> val op=BinOp("+",Number(1),x) op: BinOp = BinOp(+,Number(1.0),Var(x))

其次,Scala編譯器為case class的構造函數的參數創建以參數名為名稱的屬性,比如Val的類的參數name:String 可以直接通過 .name訪問,比如:

scala> x.name
res1: String = x

第三,編譯器為case class 構造了更自然的toString,hashCode和equals實現,它們會遞歸打印,比較case class的參數屬性。比如:

scala> println(op)
BinOp(+,Number(1.0),Var(x)) scala> op.right == Var("x") res3: Boolean = true

最后一點,Scala編譯器為case class添加了一個Copy方法,這個copy方法可以用來構造類對象的一個可以修改的拷貝。這對於使用已有的對象構造一個新實例非常方便,你只要修新創建實例的某些參數即可。 
比如我們想創建一個和op類似的新的實例,只想修改+為-,可以使用:

scala> op.copy(operator="-") res4: BinOp = BinOp(-,Number(1.0),Var(x))

以上這些慣例帶來了很多便利,這些便利也需要一些小小的代價,就是需要在class前面使用case關鍵字,而構造后的類由於自動添加了一些方法而變大了些。case class帶來的最大的好處是它們支持模式識別。

Pattern matching 
比如說你需要簡化表達式的表示方法,這里給出一個簡單的規則:

UnOp(“-”,Unop(“-”,e)) => e//負負得正 
BinOp(“+”,e,Number(0)) => e//和0加 
BinOp(”*”,e,Number(1)) => e //和1乘

使用模式匹配,在Scala我們幾乎和使用和上面規則非常類似的代碼來實現表達式的簡化:

scala> def simplifyTop(expr :Expr) :Expr = expr match {  | case UnOp("-",UnOp("-",e))=>e  | case BinOp("+",e,Number(0))=>e  | case BinOp("*",e,Number(1))=>e  | case _ => expr  |  | } simplifyTop: (expr: Expr)Expr scala> simplifyTop(UnOp("-",UnOp("-",Var("x")))) res6: Expr = Var(x) scala>

simplifyTop 定義使用了match表達式,它對應Java的switch語句,但它的語法和switch不同,它的selector 在match前面: 
selector match { alternatives}

一個模式匹配由多個可選項組成,沒個選項由case開始,每個選項定義一個模式,每個模式對應一個表達式,表達式應用到當模式匹配的時候。模式和表達式之間使用=>分隔。 
一個match表達式的結果取決於第一個匹配的可選項,當該項模式匹配時,該模式=>后的表達式被選中然后計算該表達式的值。 
一個常量模式,比如本例中的“+”和“0”, 匹配對應的常數,一個變量模式比如e,可以匹配任意的值。然后=>右邊的表示式可以應用這個變量,“_”為通配符,可以匹配任意的值。 
構造器模式,比如UnOp(“-”,e),可以匹配UnOp類型的值,這個UnOp的第一個參數為”-“,第二個參數可以為任意。

和Java的 switch語句比較,Scala的match 有以下幾個不同點:

    • match為一表達式,有返回結果,其返回結果為匹配項表示式的值。
    • match的選項沒有break,也不會自動匹配下一個選項(no fall through).
    • 如果沒有一個選項匹配,那么將拋出MatchError異常,這意味着你必須保證考慮到Match的所有的選項,因此可能你需要添加一個缺省選項。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM