从通用集合中选择类型的子集

时间:2011-08-15 15:57:51

标签: generics scala collections type-erasure

好吧,伙计们,我现在开始得到一些scala,但偶尔会有更棘手的概念。让我向您介绍水果世界:

class Fruit
class Pear extends Fruit
class Apple extends Fruit
class GrannySmith extends Apple

现在如果我想要一个新的通用集合,允许我从泛型集合中选择Fruit的子集,那该怎么办?天真的实施:

class MyArray[T](var a:Array[T]) {
  def select[U <: T] = 
    a.filter(_ match {
      case u:U => true
      case _   => false
    })
}

然而,这不起作用。

scala> var ma = new MyArray(
                        Array(
                          new Apple, 
                          new Fruit, 
                          new Pear, 
                          new GrannySmith, 
                          new Apple, 
                          new Fruit
                        ))


scala> ma.select[Apple]
res1: Array[Fruit] = Array(Apple@4d815146, Fruit@64fef26a, Pear@1ddd40f3, GrannySmith@28d320d6, Apple@3d10d68a, Fruit@1c751d58)

控制台警告未经检查的错误,在定义MyArray时使用-unchecked重新运行:

<console>:8: warning: abstract type U in type pattern U is unchecked since it is eliminated by erasure
             case u:U => true

所以我对类型擦除的理解非常模糊。我知道它在某种程度上与jvm中有限的动态类型有关,并且你有时可以使用Manifest来解决它,因为Daniel正在谈论here。我特别不明白的是这个例子是如何工作的,以及如何解决它。

我很感谢你的帮助!

1 个答案:

答案 0 :(得分:3)

这个怎么样?你甚至可以获得正确的返回类型。

ma.a.collect { case a: Apple => a }
相关问题