在 GitHub 上編輯此頁面

聯合類型

聯合類型 A | B 包含兩種類型的所有值。

trait ID
case class UserName(name: String) extends ID
case class Password(hash: Hash) extends ID

def help(id: UserName | Password) =
  val user = id match
    case UserName(name) => lookupName(name)
    case Password(hash) => lookupPassword(hash)
  ...

聯合類型是交集類型的對偶。|可交換的A | BB | A 為相同類型。

只有在明確給定聯合類型,或所有備選項式的共同超類別為透明時,編譯器才會將聯合類型指定給表達式。

這可以在以下 REPL 轉錄中看到

scala> val password = Password(123)
val password: Password = Password(123)

scala> val name = UserName("Eve")
val name: UserName = UserName(Eve)

scala> if true then name else password
val res1: ID = UserName(Eve)

scala> val either: Password | UserName = if true then name else password
val either: UserName | Password = UserName(Eve)

res1 的類型為 ID,為 UserNamePassword 的超類別,但不是最小超類別 UserName | Password。如果我們想要最小超類別,我們必須明確給定,就像 either 的類型那樣。

如果宣告共用超特質 IDtransparent,則推論行為會改變

transparent trait ID

在這種情況下,聯集類型不會擴大。

scala> if true then name else password
val res2: UserName | Password = UserName(Eve)

如果未明確宣告父類別就宣告 UserNamePassword,也會推論出更精確的聯集類型,因為在這種情況下,它們的隱含超類別為 Object,而 Object 是假設為透明的類別之一。請參閱 透明特質和類別 以取得此類類別的清單。

case class UserName(name: String)
case class Password(hash: Hash)

scala> if true then UserName("Eve") else Password(123)
val res3: UserName | Password = UserName(Eve)

更多詳細資訊