联合类型
联合类型 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 | B 与 B | 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,它是 UserName 和 Password 的超类型,但不是最小超类型 UserName | Password。如果我们想要最小超类型,则必须显式给出它,就像 either 的类型所做的那样。
如果公共超特征 ID 被声明为 transparent,则推理行为会发生变化
transparent trait ID
在这种情况下,联合类型不会被扩展。
scala> if true then name else password
val res2: UserName | Password = UserName(Eve)
如果 UserName 和 Password 在没有显式父类的情况下被声明,那么也会推断出更精确的联合类型,因为在这种情况下,它们隐含的超类是 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)