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

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

簡(jiǎn)單的示例

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

在我們?cè)敿?xì)介紹 Scala 的 Case class 和模式匹配之前,我們可以通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明一些基本概念。我們?cè)O(shè)計(jì)一個(gè)函數(shù)庫(kù),這個(gè)函數(shù)庫(kù)可以用來(lái)計(jì)算算術(shù)表達(dá)式,為簡(jiǎn)單起見(jiàn),我們?cè)O(shè)計(jì)的算術(shù)表達(dá)式只側(cè)重于變量,數(shù)字,單操作符,和雙操作符。我們可以采用如下的 Scala 類(lèi)定義:

    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

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

case classes

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

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

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

這個(gè)構(gòu)造器在嵌套使用時(shí)顯得非常簡(jiǎn)潔明了,比如我們構(gòu)建如下的表達(dá)式,這種寫(xiě)法避免了很多 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ù)名為名稱(chēng)的屬性,比如 Val 的類(lèi)的參數(shù) name:String 可以直接通過(guò) .name 訪問(wèn),比如:

    scala> x.name
    res1: String = x

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

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

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

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

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

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

Pattern matching

比如說(shuō)你需要簡(jiǎn)化表達(dá)式的表示方法,這里給出一個(gè)簡(jiǎn)單的規(guī)則:

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

使用模式匹配,在Scala我們幾乎和使用和上面規(guī)則非常類(lèi)似的代碼來(lái)實(shí)現(xiàn)表達(dá)式的簡(jiǎ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 表達(dá)式,它對(duì)應(yīng) Java 的 switch 語(yǔ)句,但它的語(yǔ)法和 switch 不同,它的 selector 在 match 前面:

selector match { alternatives}

一個(gè)模式匹配由多個(gè)可選項(xiàng)組成,沒(méi)個(gè)選項(xiàng)由 case 開(kāi)始,每個(gè)選項(xiàng)定義一個(gè)模式,每個(gè)模式對(duì)應(yīng)一個(gè)表達(dá)式,表達(dá)式應(yīng)用到當(dāng)模式匹配的時(shí)候。模式和表達(dá)式之間使用=>分隔。

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

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

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

和 Java 的 switch 語(yǔ)句比較,Scala 的 match 有以下幾個(gè)不同點(diǎn):

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