1

注意:这是关于类型转换的问题,而不是类型转换。请停止更改标题。

我想编写一个通用函数,它根据运行时指定的retrieve[F]返回一个:List[F]F

trait Foo
trait Bar extends Foo
trait Baz extends Foo

def retrieve[F <: Foo](implicit m: Manifest[F]): List[F] = m.erasure match {
  case x if x.isAssignableFrom(classOf[Bar]) => List[Bar]().asInstanceOf[List[F]]
  case x if x.isAssignableFrom(classOf[Baz]) => Nil
  case _ => Nil
}

是否有更类型安全的方法来执行此操作(即不诉诸清单,isAssignableFrom并将每个返回值转换为List[F])?

4

2 回答 2

0

消除强制转换的一种方法是使用存在类型:

trait Foo
trait Bar extends Foo
trait Baz extends Foo                                       

case object Bar1 extends Bar                                
case object Baz1 extends Baz                                

def retrieve[F <: Foo](implicit m: Manifest[F]): List[_ <: Foo] = m.erasure match {
  case x if x.isAssignableFrom(classOf[Bar]) => List[Bar]()  
  case x if x.isAssignableFrom(classOf[Baz]) => Nil  
  case _ => Nil
}           

不幸的是,似乎仍然丢失了一些类型信息,因为在编译时不知道Foo将返回哪个实现:

val foos: List[Foo] = retrieve[Bar]                         
// val bars: List[Bar] = retrieve[Bar] // does not compile
于 2012-10-29T20:58:22.700 回答
0

我最终使用类型类来实现它。不会丢失类型信息,也不需要类型套管(或类型转换)。

我能看到的唯一奇怪的一点是选择直接retrieveBarandBaz类进行拉皮条,但这似乎可以解决问题。

trait Foo
case class Bar(x: String) extends Foo
case class Baz(x: String) extends Foo

trait Retrievable[A] {
  def retrieve: List[A]
}

val _bars: List[Bar] = List(Bar("bar a"),Bar("bar b"))
val _bazs: List[Baz] = List(Baz("baz 1"),Baz("baz 2"))

implicit def barsRetrievable(x: Class[Bar]): Retrievable[Bar] =
  new Retrievable[Bar] {
    override def retrieve: List[Bar] = _bars
  }

implicit def foosRetrievable(x: Class[Baz]): Retrievable[Baz] =
  new Retrievable[Baz] {
    override def retrieve: List[Baz] = _bazs
  }

val bars: List[Bar] = classOf[Bar].retrieve
// bars: List(Bar(bar a), Bar(bar b))

val bazs: List[Baz] = classOf[Baz].retrieve
// bazs: List(Baz(baz 1), Baz(baz 2))
于 2013-08-05T22:37:36.770 回答