Scala學(xué)習(xí)筆記(七) Sealed Class 和 Enumeration

1. Sealed Class

1.1 sealed class

先上一段代碼,看看sealed是怎么使用的

scala> sealed abstract class Drawing
defined class Drawing

scala> case class Point(x: Int, y: Int) extends Drawing
defined class Point

scala> case class Circle(p: Point, r: Int) extends Drawing
defined class Circle

scala> case class Cylinder(c: Circle, h: Int) extends Drawing
defined class Cylinder

scala> def what(d: Drawing) = d match {
     |   case Point(_,_) => "點(diǎn)"
     |   case Circle(_,_) => "圓"
     | }
<console>:16: warning: match may not be exhaustive.
It would fail on the following input: Cylinder(_, _)
       def what(d: Drawing) = d match {
                              ^
what: (d: Drawing)String

在這里what()方法報(bào)錯(cuò)了,主要是因?yàn)檫€缺少了對(duì)Cylinder的匹配,只要改成如下的代碼就可以正常運(yùn)行了。

scala> def what(d: Drawing) = d match {
     |   case Point(_,_) => "點(diǎn)"
     |   case Circle(_,_) => "圓"
     |   case Cylinder(_,_) => "柱"
     | }
what: (d: Drawing)String

在使用模式匹配的時(shí)候,使用 sealed 修飾某個(gè) class 的目的是讓 Scala 知道所有 case 的情況,否則會(huì)編譯報(bào)錯(cuò)。

當(dāng)然,也有例外的時(shí)候,使用 @unchecked 告訴編譯器可以不用檢查也能編譯通過(guò)。

scala> def what(d: Drawing) = (d: @unchecked) match {
     |   case Point(_,_) => "點(diǎn)"
     |   case Circle(_,_) => "圓"
     | }
what: (d: Drawing)String

還有一點(diǎn)很重要,當(dāng)使用 sealed 來(lái)修飾某個(gè) class 時(shí),繼承該類(lèi)的其他子類(lèi)需要跟父類(lèi)在同一文件中。

1.2 sealed trait

同樣,先上一段代碼

scala> sealed trait Color
defined trait Color

scala> final case object Red extends Color
defined object Red

scala> final case object Green extends Color
defined object Green

scala> final case object Blue extends Color
defined object Blue

scala> val colors = List(Red,Green,Blue)
colors: List[Product with Serializable with Color] = List(Red, Green, Blue)

可以看到“Product with Serializable with Color”這一句。
case class 會(huì)自動(dòng)繼承兩個(gè)trait:Product 和 Serializable。

Product Trait 讓 case class 被擴(kuò)展為具有Algebraic Data Type,或者說(shuō)具有產(chǎn)品類(lèi)型。

Serializable Trait 讓 case class 可以被視為一個(gè)純粹的數(shù)據(jù),能夠被序列化。

如果你想避免看到這個(gè)實(shí)現(xiàn)的細(xì)節(jié),可以提前聲明Color已經(jīng)擴(kuò)展了 Product 和 Serializable 這些 trait。

scala> sealed trait Color extends Product with Serializable
defined trait Color

scala> final case object Red extends Color
defined object Red

scala> final case object Green extends Color
defined object Green

scala> final case object Blue extends Color
defined object Blue

scala> val colors = List(Red, Green, Blue)
colors: List[Color] = List(Red, Green, Blue)

sealed 修飾的 trait 也只能在當(dāng)前文件里面被繼承。

1.3 sealed abstract 和 abstract class 的區(qū)別

sealed class的所有子類(lèi),無(wú)論是否是抽象類(lèi),都必須跟 sealed class 在同一個(gè)文件中。

而abstract class并沒(méi)有這樣的規(guī)定。

2. Enumeration

Scala 中并沒(méi)有枚舉類(lèi)型,但是在標(biāo)準(zhǔn)庫(kù)中有scala.Enumeration??梢詳U(kuò)展Enumeration類(lèi),調(diào)用Value方法來(lái)初始化枚舉中的可能值。

/**
  * Created by tony on 2017/4/12.
  */
object Source extends Enumeration {

  type Source = Value

  //枚舉的定義
  val Net, Memory, Disk = Value
}

import Source._

object Data extends App {

  def loadData(source: Source){
    source match {
      case Net => println ("source type is " + source)
      case Memory => println ("source type is " + source)
      case Disk => println ("source type is " + source)
      case _ => println ("unknown type")
    }
  }

  val net = Source(0) // Calls Enumeration.apply
  println(loadData(net)) // source type is Net

  // 遍歷Source枚舉
  for (s <- Source.values)
    println(s.id + ":" + s)
}

打印的結(jié)果:

source type is Net
()
0:Net
1:Memory
2:Disk

在定義枚舉值的時(shí)候也可以自定義id和名稱,Source2重新定義了幾個(gè)枚舉。

/**
  * Created by tony on 2017/4/12.
  */
object Source2 extends Enumeration {

  type Source = Value

  //枚舉的定義
  val Net, Memory, Disk = Value
  val Other = Value(10,"other source")
}

object Data2 extends App {

  // 遍歷Source枚舉
  for (s <- Source2.values)
    println(s.id + ":" + s)
}

打印的結(jié)果:

0:Net
1:Memory
2:Disk
10:other source

最終,我們可以得到:

  • Scala中的枚舉使用輕量級(jí)Enumeration進(jìn)行實(shí)現(xiàn)
  • Scala中的枚舉其實(shí)是一個(gè)伴隨對(duì)象
  • Scala中的枚舉沒(méi)有方法重寫(xiě)功能
  • Scala中的枚舉其實(shí)都是Enumeration.Value這個(gè)對(duì)象

總結(jié)

本篇筆記仍然是為了 Scala 模式匹配所做的鋪墊。在模式匹配中會(huì)講到Sealed Class,所以先整理出來(lái)。除了Sealed用法之外,還整理了Enumeration的相關(guān)用法。

先前的文章:
Scala學(xué)習(xí)筆記(六) Scala的偏函數(shù)和偏應(yīng)用函數(shù)

Scala學(xué)習(xí)筆記(五) 抽象類(lèi)以及類(lèi)中的一些語(yǔ)法糖
Scala學(xué)習(xí)筆記(四) 類(lèi)的初步
Scala學(xué)習(xí)筆記(三)
Scala學(xué)習(xí)筆記(二)
Scala學(xué)習(xí)筆記(一)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容