此文件頁面專屬於 Scala 3,可能涵蓋 Scala 2 中沒有的新概念。除非另有說明,此頁面中的所有程式碼範例都假設您使用的是 Scala 3。
用於類型時,|
算子會建立所謂的聯合類型。類型 A | B
代表值不是類型 A
,就是類型 B
。
在以下範例中,help
方法接受一個名為 id
的參數,其聯合類型為 Username | Password
,可以是 Username
,也可以是 Password
case class Username(name: String)
case class Password(hash: Hash)
def help(id: Username | Password) =
val user = id match
case Username(name) => lookupName(name)
case Password(hash) => lookupPassword(hash)
// more code here ...
我們透過使用樣式比對來區分兩個選項來實作 help
方法。
此程式碼是一個彈性和類型安全的解決方案。如果您嘗試傳入 Username
或 Password
以外的類型,編譯器會將其標示為錯誤
help("hi") // error: Found: ("hi" : String)
// Required: Username | Password
如果您嘗試將 case
新增到與 Username
或 Password
類型不符的 match
表達式,也會產生錯誤
case 1.0 => ??? // ERROR: this line won’t compile
聯合類型的替代方案
如所示,聯合類型可用於表示數種不同類型的替代方案,而不需要這些類型成為自訂類別階層的一部分,也不需要明確包裝。
預先規劃類別階層
沒有聯合類型,就需要預先規劃類別階層,如下面的範例所示
trait UsernameOrPassword
case class Username(name: String) extends UsernameOrPassword
case class Password(hash: Hash) extends UsernameOrPassword
def help(id: UsernameOrPassword) = ...
預先規劃無法很好地擴充,因為例如 API 使用者的需求可能無法預見。此外,使用 UsernameOrPassword
等標記特徵來混淆類型階層也會使程式碼更難以閱讀。
標記聯合
另一種替代方案是定義一個獨立的列舉類型,如下所示
enum UsernameOrPassword:
case IsUsername(u: Username)
case IsPassword(p: Password)
列舉 UsernameOrPassword
代表 Username
和 Password
的標記聯集。然而,這種建模聯集的方式需要明確包裝和解包,例如,Username
不是 UsernameOrPassword
的子類型。
聯集類型的推論
編譯器僅在明確給予聯集類型時,才會將聯集類型指定給表達式。例如,給定這些值
val name = Username("Eve") // name: Username = Username(Eve)
val password = Password(123) // password: Password = Password(123)
此 REPL 範例顯示在將變數繫結到 if
/else
表達式的結果時,如何使用聯集類型
scala> val a = if true then name else password
val a: Object = Username(Eve)
scala> val b: Password | Username = if true then name else password
val b: Password | Username = Username(Eve)
a
的類型是 Object
,它是 Username
和 Password
的超類型,但不是最小超類型 Password | Username
。如果您想要最小超類型,您必須明確給予,就像對 b
所做的那樣。
聯集類型是交集類型的對偶。就像交集類型的
&
,|
也是可交換的:A | B
與B | A
是同種類型。
此頁面的貢獻者
內容
- 簡介
- Scala 功能
- 為什麼選擇 Scala 3?
- Scala 體驗
- Hello, World!
- REPL
- 變數和資料類型
- 控制結構
- 網域建模
- 方法
- 一級函數
- 單例物件
- 集合
- 脈絡抽象
- 頂層定義
- 摘要
- 初探類型
- 字串內插
- 控制結構
- 網域建模
- 工具
- 物件導向建模
- 函式程式建模
- 方法
- 方法特性
- Scala 3 中的主要方法
- 摘要
- 函式
- 匿名函式
- 函式變數
- Eta 展開
- 高階函式
- 撰寫您自己的 map 方法
- 建立會傳回函式的函式
- 摘要
- 封裝和匯入
- Scala 集合
- 集合類型
- 集合方法
- 摘要
- 函式程式設計
- 什麼是函式程式設計?
- 不可變值
- 純函式
- 函式是值
- 函式錯誤處理
- 摘要
- 類型和類型系統
- 推論類型
- 泛型
- 交集類型
- 聯合類型
- 代數資料類型
- 變異
- 不透明類型
- 結構類型
- 相依函式類型
- 其他類型
- 脈絡抽象
- 擴充方法
- 脈絡參數
- 脈絡界限
- Given 匯入
- 類型類別
- 多重等式
- 隱式轉換
- 摘要
- 並行處理
- Scala 工具
- 使用 sbt 建立和測試 Scala 專案
- 工作表
- 與 Java 互動
- 供 Java 開發人員使用的 Scala
- 供 JavaScript 開發人員使用的 Scala
- 供 Python 開發人員使用的 Scala
- 後續步驟