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

キャストを排除する1つの方法は、実存型を使用することです。

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

型クラスを使用してこれを実装することになりました。型情報が失われることはなく、型ケーシング(または型キャスト)も必要ありません。

私が見ることができる唯一の奇妙なビットは、クラスとクラスに直接ポン引きretrieveすることを選択することですが、それはトリックを行うようです。BarBaz

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 に答える