2012-10-04 45 views
1

注意:這是一個關於型套管,而不是類型鑄造的問題。請停止更改標題。如何避免型套

我想編寫一個通用功能retrieve[F]基於在運行時指定的F它返回一個List[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])?消除鑄件

+1

我沒有看到任何鑄件 –

+0

更新了一個鑄造的例子。 – earldouglas

+0

我想你可以通過恢復上次編輯來避免它。有什麼意義? –

回答

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)) 
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