复合类型的意外行为

Unexpected behavior with compound types

我有3个特质

  trait A
  trait B
  trait AB extends A with B

和一个方法

def collect[E: Manifest](list: List[Any]) =
    list flatMap {
      case record: E => Some(record)
      case _         => None
    }

对于给定的列表

val list = new A {} :: new A {} :: new A with B {} :: new AB {} :: Nil

我用不同的类型调用了 collect

collect[A with B](list) // collect all elements from the list
collect[AB](list) // collect only the last element

谁能解释 A with BAB 类型的行为差异?

非常不直观但它符合规范。首先,引用 Manifest docs(强调我的):

A Manifest[T] is an opaque descriptor for type T. Its supported use is to give access to the erasure of the type

所以在 collect[A with B] 中,我们正在匹配 A with Berasure。那是什么?如果我们查看规范的 Type erasure 部分,我们会读到:

The erasure of a compound type T1 with ... with Tn is the erasure of the intersection dominator of T1, ..., Tn

并且 交叉点支配符 被定义为(再次强调我的)

The intersection dominator of a list of types T1, ..., Tn is computed as follows. Let Ti1, ..., Tim be the subsequence of types Ti which are not supertypes of some other type Tj. If this subsequence contains a type designator Tc that refers to a class which is not a trait, the intersection dominator is Tc. Otherwise, the intersection dominator is the first element of the subsequence, Ti1

在我们的例子中,子序列是 A,B,因为它们没有任何子类型关系,因此 A with B 的擦除是 A,所以在 collect[A with B] 我们实际上匹配的是 A.

您可以通过查看 collect[B with A] 的输出轻松看到此行为,and/or 添加一个 new B {} 到您的 list