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 B
和AB
类型的差异吗?
它非常不直观,但它符合规范.首先,引用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 B
是A
,因此collect[A with B]
我们实际上是匹配的A
.
您可以通过查看输出collect[B with A]
和/或添加new B {}
到您的输出来轻松查看此行为list
.