在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

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

簡單的示例

本專題側(cè)重介紹 Scala 的 case class 和 pattern matching (模式匹配),這倆個兩個程序結(jié)構(gòu)對于處理樹結(jié)構(gòu)的數(shù)據(jù)非常有幫助。 Scala 的 case class 使得對對象進行模式匹配變得非常方便,簡單的來說,Scala 的 case clas s就是在普通的類定義前加 case 這個關(guān)鍵字,然后你可以對這些類來模式匹配。

在我們詳細介紹 Scala 的 Case class 和模式匹配之前,我們可以通過一個簡單的例子來說明一些基本概念。我們設(shè)計一個函數(shù)庫,這個函數(shù)庫可以用來計算算術(shù)表達式,為簡單起見,我們設(shè)計的算術(shù)表達式只側(cè)重于變量,數(shù)字,單操作符,和雙操作符。我們可以采用如下的 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 和四個子類(分別代表變量,數(shù)值,單操作符,雙操作符),Scala 允許我們不定義類的實現(xiàn),實際我們是 class C 和 class C {} 是等價的。

case classes

我們可以看到上面的四個子類定義前面我們使用了 case 關(guān)鍵字,使用了 case 關(guān)鍵字的類定義就是case classes。使用這個關(guān)鍵字,Scala 編譯器會自動為你定義的類生成一些成員。

首先,編譯器為 case class 生成一個同名的對象構(gòu)造器(Factory Method),也就是你可以使用 Var(“x”) 來創(chuàng)建一個類的實例,而無需使用 new Var(“x”)。

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

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

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

其次,Scala 編譯器為 case class 的構(gòu)造函數(shù)的參數(shù)創(chuàng)建以參數(shù)名為名稱的屬性,比如 Val 的類的參數(shù) name:String 可以直接通過 .name 訪問,比如:

    scala> x.name
    res1: String = x

第三,編譯器為 case class 構(gòu)造了更自然的 toString,hashCode 和 equals 實現(xiàn),它們會遞歸打印,比較 case class 的參數(shù)屬性。比如:

    scala> println(op)
    BinOp(+,Number(1.0),Var(x))

    scala> op.right == Var("x")
    res3: Boolean = true

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

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

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

Pattern matching

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

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

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

    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 表達式,它對應(yīng) Java 的 switch 語句,但它的語法和 switch 不同,它的 selector 在 match 前面:

selector match { alternatives}

一個模式匹配由多個可選項組成,沒個選項由 case 開始,每個選項定義一個模式,每個模式對應(yīng)一個表達式,表達式應(yīng)用到當(dāng)模式匹配的時候。模式和表達式之間使用=>分隔。

一個 match 表達式的結(jié)果取決于第一個匹配的可選項,當(dāng)該項模式匹配時,該模式 => 后的表達式被選中然后計算該表達式的值。

一個常量模式,比如本例中的 “+” 和 “0” ,匹配對應(yīng)的常數(shù),一個變量模式比如 e,可以匹配任意的值。然后=>右邊的表示式可以應(yīng)用這個變量,“_”為通配符,可以匹配任意的值。

構(gòu)造器模式,比如 UnOp(“-“,e),可以匹配 UnOp 類型的值,這個 UnOp 的第一個參數(shù)為”-“,第二個參數(shù)可以為任意。

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

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