0605.案例類別(case class)

case class
該語言一定要具備足夠的可擴展性,以使讀者無需徹底改變該語言就能夠將它用作一個功能更強大的語言的核心。這意味著該語言一定要可以被輕易地擴展,並要儘量保持封裝性,用起來不會有任何的阻礙。 - DSL






case class 特點


Scala 的 case class 是一種提供了豐富資料、使用了非常淺薄並封裝的 class,它俱有的一些特性使它很適合構建 AST。最俱代表性的是 Scala 其內置的 樣式匹配 (pattern match) , 相當於函數式程式語言中常用的 代數型別(Algebraic Type) 。使 scala 開發者得以使用某些假設的預設值來創建一個 class 的一種便捷機制。
  1. Scala 的 case 類別也是正規的類別,暴露其建構子參數,並通過模式匹配提供遞歸解構機制
  2. 為了便於 case 類別實例的構建,Scala 不需要使用 new 原語。只要簡單地把類別名用作函數即可。
    1. 工廠方法
  3. case 類別的建構子參數被當作公開值並可以直接被存取
    1. 相當於 (val name: type, ...)
  4. 對於每個 case 類別,Scala 編譯器將產生實作了結構相等性檢查的 equals 方法和一個 toString 方法。
  5. 只有在分解資料結構的時候用到了模式匹配的情況下,定義 case 類別才是有意義的。
  6. case class 可由 abstract class 或一般的 class 斷承.
  7. case class 可以呈巢狀嵌套, 再配合 _ 或者變數型態, 來表達更複雜的 Pattern Matching 規則.


case class VS. object


  1. 相同點
    1. 不使用 new 來產生實例(instance).
  2. 不同點
    1. case class 可以擁有建構子(Constructor), 但 object 不可.





Example



scala> case class B(name: Int)
defined class B

scala> val a = B(2)
a: B = B(2)


scala> case class Wisdom(a: Int, b: Int)
defined class Wisdom

scala> val w = Wisdom(2, 2)
w: Wisdom = Wisdom(2,2)

scala> print (w.a)
2

scala> w.

a                    asInstanceOf         b                    canEqual             copy                 copy$default$1
copy$default$2       equals               getClass             hashCode             isInstanceOf         notify
notifyAll            productArity         productElement       productElementName   productElements      productIterator
productPrefix        toString             wait



abstract class WisdomFish
case class F2(x: Int) extends WisdomFish
...

F1 match {
case F2(n) =>
println(n)


2.8+  copy( )
scala> case class foo(a:Int, b: Int)
defined class foo

scala> val x = foo(2, 3)
x: foo = foo(2,3)

scala> x.copy(b = 33)
res5: foo = foo(2,33)


scala> x.

a                    asInstanceOf         b                    canEqual             copy                 copy$default$1
copy$default$2       equals               getClass             hashCode             isInstanceOf         notify
notifyAll            productArity         productElement       productElementName   productElements      productIterator
productPrefix        toString             wait






De-compiled to Java Code


class K(x: Int) { ... }

public class K extends java.lang.Object implements scala.ScalaObject {
    public K(int);
    public int $tag()       throws java.rmi.RemoteException;
}



Scala 編譯器不僅可按照我們對它的期望來產出預期的構造子 — Scala 編譯器還可以產出常規意義上的 equals()、toString() 和 hashCode() 實作。事實上,這種 case class 很普通(即它沒有其他的成員),因此 case class 宣告後面的大括號的內容是可選的

case
class K2(x: Int) { ... }

public class K2 extends java.lang.Object implements scala.ScalaObject, scala.Product, java.io.Serializable {
    public K2(int);
    public java.lang.Object productElement(int);
    public int productArity();
    public java.lang.String productPrefix();
    public boolean equals(java.lang.Object);
    public java.lang.String toString();
    public int hashCode();
    public int $tag();
    public int x();
}

public final class K2$ extends java.lang.Object implements scala.Function1,scala.ScalaObject{
    public static final K2$ MODULE$;
    public static {};
    public K2$();
    public java.lang.Object apply(java.lang.Object);
    public K2 apply(int);
    public scala.Some unapply(K2);
    public int $tag()       throws java.rmi.RemoteException;
    public scala.Function1 andThen(scala.Function1);
    public scala.Function1 compose(scala.Function1);
    public java.lang.String toString();
}




case class 的價值


伴隨 case class 發生了很多傳統 class 通常不會引發的事情。這是因為 case class 是要與 Scala 的樣式匹配結合使用的。 使用 case class 與使用傳統 class 有些不同,這是因為通常它們都不是通過傳統的 「new」 語法構造而成的;事實上,它們通常是通過一種名稱與類相同的工廠方法來創建的

case class 的真正價值體現在模式匹配中,模式匹配類似 Java 的 「switch/case」,只不過它的本領和功能更加強大。模式匹配不僅能夠檢查匹配構造的值,從而執行值匹配,還可以針對局部通配符(類似局部 「預設值」 的東西)匹配值,case 還可以包括對測試匹配的保護,來自匹配標準的值還可以綁定於區域變數,甚至符合匹配標準的類型本身也可以進行匹配。




DSL







Reference


  1. AST(抽象語法樹)[insied]
  2. 樣式匹配(Pattern Matching)
  3. A Tour of Scala: Pattern Matching, http://www.scala-lang.org/node/120
  4. A Tour of Scala: Case Classes, http://www.scala-lang.org/node/107
  5. λ演算(lambda calculus), http://en.wikipedia.org/wiki/Lambda_calculus
  6. 從Java走進Scala:構建計算器 case類和模式匹配(1), http://developer.51cto.com/art/200906/130364.htm
  7. http://caterpillar.onlyfun.net/Gossip/Scala/CaseClass.html