scala中的sealed

通凡發表於2018-09-03

sealed關鍵字在scala的集合和模式匹配上面應用較多,本篇文章說明sealed的使用場景以及為什麼使用sealed。

A sealed class cannot have any new subclasses added except the ones in the same file.這是sealed關鍵字比較官方的解釋,意思是隻在同一個檔案中的新增其子類,除此以外不能有任何的子類(區別於java中任何類都可以進行整合操作),從這一點可以看出,其主要作用是用於設計上的,但是也有功能上的,下面從設計和功能兩方面進行說明。

1. 防止濫用繼承

sealed關鍵字可以修飾類和特質(特質)密封類提供了一種約束:不能在類定義的檔案之外定義任何新的子類。這樣可以防止繼承的濫用,示例如下:

scala原始碼中List的實現用到了sealed關鍵字,抽象類List有sealed關鍵字修飾,在Nil::兩個操作中,分別繼承了該List的抽象類。當我們實現自己的list集合時,進行繼承,將會出現錯誤。

抽象類List有sealed關鍵字修飾,接下來Nil和::分別繼承了該List抽象類。那我們來嘗試實現基於List實現一個自己的List:

scala> class NewList extends List
<console>:7: error: illegal inheritance from sealed class List
       class NewList extends List123

該類在編譯的時候就不能通過,我們是不能在外部檔案繼承List類。所以,如果子類都明確的情況下,這是最為重要的前提,為了防止繼承濫用,為抽象類新增sealed。(這一點主要是設計上的作用,在java語言中只有yes 和 no,在scala中提出更為重要的you should use it correctly rather than freely


2. 模式匹配校驗子類

模式匹配是scala非常好用的一個語法特性。pattern使用的場景總結起來大約以下幾類:

- Wildcard patterns // _ 統配
- Constant patterns // 常量
- Variable patterns // 變數
- Constructor patterns // 建構函式
- Sequence patterns // 比如List(,). 如果需要匹配剩餘的話使用List(0,_*)
- Tuple patterns // (a,b,c)
- Typed patterns // 使用型別匹配 case a:Map[,]
- asInstanceOf[]
- isInstanceOf[]
- note(dirlt):這裡需要注意容器型別擦除.Array例外因為這個是java內建型別

但是,當我們頻繁改變條件,我們可能會忘了修改相應的case,那麼這種情況就可能會出現錯誤。看下邊例子:

scala> :pas
// Entering paste mode (ctrl-D to finish)
  abstract class People
  case object American extends People
  case object Japanese extends People
  case object Chinese extends People
  case object Russia extends People

  def people(p: People) = p match {
    case American ⇒ println("American person")
    case Japanese ⇒ println("Japanese person")
    case Chinese ⇒ println("Chinese person")
  }

// Exiting paste mode, now interpreting.

defined class People
defined object American
defined object Japanese
defined object Chinese
defined object Russia
people: (p: People)Unit

scala> people(American)
American person

scala> people(Russia)
scala.MatchError: Russia (of class Russia$)
  at .people(<console>:13)
  ... 33 elided12345678910111213141516171819202122232425262728293031

這時我們為People加上sealed,當我們編譯程式碼時得到了一個警告:

<console>:18: warning: match may not be exhaustive.
It would fail on the following input: Russia

多溫馨的一個提示啊。事情都不是絕對的,如果確定people只處理美國,日本,中國人,編譯時總是給這麼個警告也挺鬧心。能破嗎?可定能,看程式碼:

  def people(p: People) = (p: @unchecked) match {
    case American ⇒ println("American person")
    case Japanese ⇒ println("Japanese person")
    case Chinese ⇒ println("Chinese person")
  }

3. sealed總結

給我個人的感覺,這個關鍵字主要是在設計上的限制,更加規範你的程式碼,使你的程式碼更加的優雅,當然最後要對本文參考如下三篇部落格,表示感謝!

https://blog.csdn.net/ZCF1002797280/article/details/50848487

https://www.cnblogs.com/rollenholt/p/4192758.html

https://yq.aliyun.com/articles/8611

相關文章