注意:这是关于type-casing的问题,而不是类型转换。请停止更改标题。
我想编写一个泛型函数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]
)?
答案 0 :(得分: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
答案 1 :(得分:0)
我最终使用类型类实现了这个。不丢失类型信息,也不需要类型套管(或铸造型)。
我能看到的唯一奇怪的一点就是选择直接将retrieve
移植到Bar
和Baz
类,但它似乎可以解决这个问题。
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))