联合类型
联合类型 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)