复合类型的意外行为

St.*_*St. 6 types scala pattern-matching type-erasure

我有3个特征

  trait A
  trait B
  trait AB extends A with B
Run Code Online (Sandbox Code Playgroud)

和方法

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

对于给定的列表

val list = new A {} :: new A {} :: new A with B {} :: new AB {} :: Nil
Run Code Online (Sandbox Code Playgroud)

collect用不同的类型调用

collect[A with B](list) // collect all elements from the list
collect[AB](list) // collect only the last element
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释行为A with BAB类型的差异吗?

Edu*_*bes 5

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

Manifest [T]是类型T的不透明描述符.它支持的用途是访问类型的擦除

因此,在collect[A with B]我们的匹配删除A with B.那是什么?如果我们查看规范的Type erasure部分,我们会看到:

带有Tn的复合型T1的擦除是T1,...,Tn的交叉支配者的擦除

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

类型T1,...,Tn列表的交集支配者计算如下.设Ti1,...,Tim是类型Ti的子序列,它不是某些其他类型Tj的超类型.如果该子序列包含引用不是特征的类的类型指示符Tc,则交集支配者是Tc.否则,交集支配者是序列Ti1 的第一个元素

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

您可以通过查看输出collect[B with A]和/或添加new B {}到您的输出来轻松查看此行为list.