问题描述
我有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 B
和AB
类型的行为差异?
Could anyone explain the difference in behavior for A with B
and AB
types?
推荐答案
非常不直观,但符合规范.首先,引用 Manifest 文档(强调我的):
It is highly unintuitive but it conforms to the specification. First, quoting from the Manifest docs (emphasis mine):
Manifest[T] 是类型 T 的不透明描述符.它支持的用途是允许访问类型的擦除
所以在collect[A with B]
中,我们匹配A with B
的擦除.那是什么?如果我们查看 类型擦除 部分,我们阅读:
So in collect[A with B]
we are matching the erasure of A with B
. And what is that? if we look at the Type erasure section of the spec, we read:
复合类型T1 with ... with Tn的擦除是对T1, ..., Tn的交集支配项的擦除
和交集支配者被定义为(再次强调我的)
and the intersection dominator is defined as (again, emphasis mine)
类型列表 T1, ..., Tn 的交集支配子计算如下.让 Ti1, ..., Tim 是类型 Ti 的子序列,这些类型不是其他类型 Tj 的超类型.如果这个子序列包含一个类型指示符Tc,它指的是一个不是特征的类,则交集支配者是Tc.否则,交集支配者是子序列的第一个元素,Ti1
在我们的例子中,子序列是 A,B
因为它们没有任何子类型关系,因此 A with B
的擦除是 A
,所以在 collect[A with B]
中,我们实际上匹配了 A
.
In our case the subsequence is A,B
as they don't have any subtyping relationship, and thus the erasure of A with B
is A
, so that in collect[A with B]
we are actually matching A
.
您可以通过查看 collect[B with A]
的输出和/或向您的 添加
.new B {}
的输出来轻松查看此行为列表
You can easily see this behavior by looking at the output of collect[B with A]
, and/or adding a new B {}
to your list
.
这篇关于复合类型的意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!