Scala的案例類和類之間有什麼區別?

我在Google中搜索了case classclass之間的區別。 每一個人都提到,當您要在類上進行模式匹配時,請使用用例類。 不然,使用類,還說起一些額外的好處,例如equals和哈希碼覆蓋。 可是,這些是爲何應該使用案例類而不是類的惟一緣由嗎? app

我猜應該在Scala中使用此功能有一些很是重要的緣由。 有什麼解釋?是否有資源能夠從中學習更多有關Scala案例類的信息? 函數


#1樓

沒有人提到案例類具備val構造函數參數,但這也是常規類的默認值( 我認爲這在Scala的設計中是不一致的)。 達里奧(Dario)在他指出它們「 不可變 」的地方暗示了這一點。 學習

請注意,您能夠經過爲案例類在每一個構造函數參數前添加var來覆蓋默認值。 可是,使案例類可變則會致使其equalshashCode方法具備時變性。[1] 優化

sepp2k已經提到案例類自動生成equalshashCode方法。 spa

也沒有人提到案例類自動建立與該類同名的伴隨object ,其中包含applyunapply方法。 apply方法能夠構造實例,而無需添加new 。 在unapply提取方法使圖案匹配,其餘人說起。 設計

另外,編譯器還優化了match速度-案例類的case模式匹配[2]。 code

[1] 案例類別很酷 orm

[2] 案例分類和提取器,第15頁對象


#2樓

案例類能夠看做是普通且不可變的數據保存對象,應僅取決於其構造函數參數繼承

這個功能概念使咱們可以

  • 使用緊湊的初始化語法( Node(1, Leaf(2), None))
  • 使用模式匹配分解它們
  • 隱式定義相等比較

與繼承結合使用,case類用於模擬代數數據類型

若是對象在內部執行狀態計算或表現出其餘複雜的行爲,則應爲普通類。


#3樓

  • 案例類能夠進行模式匹配
  • 案例類自動定義哈希碼並等於
  • 案例類自動爲構造函數參數定義getter方法。

(您已經提到了除最後一個之外的全部內容)。

這些是普通班級的惟一區別。


#4樓

從技術上講,類和案例類之間沒有區別-即便編譯器在使用案例類時確實優化了某些內容。 可是,案例類用於取消特定模式的樣板,該特定模式正在實現代數數據類型

這種類型的一個很是簡單的例子是樹。 例如,能夠像這樣實現一個二叉樹:

sealed abstract class Tree
case class Node(left: Tree, right: Tree) extends Tree
case class Leaf[A](value: A) extends Tree
case object EmptyLeaf extends Tree

這使咱們可以執行如下操做:

// DSL-like assignment:
val treeA = Node(EmptyLeaf, Leaf(5))
val treeB = Node(Node(Leaf(2), Leaf(3)), Leaf(5))

// On Scala 2.8, modification through cloning:
val treeC = treeA.copy(left = treeB.left)

// Pretty printing:
println("Tree A: "+treeA)
println("Tree B: "+treeB)
println("Tree C: "+treeC)

// Comparison:
println("Tree A == Tree B: %s" format (treeA == treeB).toString)
println("Tree B == Tree C: %s" format (treeB == treeC).toString)

// Pattern matching:
treeA match {
  case Node(EmptyLeaf, right) => println("Can be reduced to "+right)
  case Node(left, EmptyLeaf) => println("Can be reduced to "+left)
  case _ => println(treeA+" cannot be reduced")
}

// Pattern matches can be safely done, because the compiler warns about
// non-exaustive matches:
def checkTree(t: Tree) = t match {
  case Node(EmptyLeaf, Node(left, right)) =>
  // case Node(EmptyLeaf, Leaf(el)) =>
  case Node(Node(left, right), EmptyLeaf) =>
  case Node(Leaf(el), EmptyLeaf) =>
  case Node(Node(l1, r1), Node(l2, r2)) =>
  case Node(Leaf(e1), Leaf(e2)) =>
  case Node(Node(left, right), Leaf(el)) =>
  case Node(Leaf(el), Node(left, right)) =>
  // case Node(EmptyLeaf, EmptyLeaf) =>
  case Leaf(el) =>
  case EmptyLeaf =>
}

請注意,樹使用相同的語法構造和解構(經過模式匹配),這也正是它們的打印方式(減去空格)。

而且它們還能夠與哈希映射或集一塊兒使用,由於它們具備有效,穩定的hashCode。


#5樓

Scala中的case類構造也能夠看做是刪除某些樣板的便利。

在構造案例類時,Scala爲您提供瞭如下內容。

  • 它建立一個類及其伴隨對象
  • 它的伴隨對象實現了您能夠用做工廠方法的apply方法。 您將得到沒必要使用new關鍵字的語法優點。

因爲該類是不可變的,所以您將得到訪問器,這些訪問器僅是該類的變量(或屬性),而沒有變種器(所以沒法更改變量)。 構造函數參數能夠做爲公共只讀字段自動提供給您。 比Java bean構造好用得多。

  • 默認狀況下,您還得到hashCodeequalstoString方法,而且equals方法在結構上比較對象。 生成copy方法以可以克隆對象(某些字段具備提供給該方法的新值)。

如前所述,最大的優點是您能夠在案例類上進行模式匹配。 這樣作的緣由是由於您得到了unapply方法,該方法使您能夠解構case類以提取其字段。


從本質上講,在建立案例類(或案例對象,若是您的類不帶參數)時從Scala得到的內容是單例對象,其目的是用做工廠提取器

相關文章
相關標籤/搜索