2015-04-03 41 views
1

我有它的成員變量,其被限制爲特定類型的中的一個的類型的情況下類協變:提取成員時,所述構件協變該類型

case class MyCount[+T <: Identifier](
    id: T, 
    count: Long, 
) 

標識符與兩個具體的實現密封的特點,雖然我不相信這對於重要的問題:

sealed trait Identifier 
case class IdentifierFoo(...) implements Identifier 
case class IdentifierBar(...) implements Identifier 

鑑於MyCount[Identifier]集合我想:

  1. 提取所有MyCount[IdentifierFoo]
  2. 有結果集合有型SomeCollection[MyCount[IdentifierFoo]]

做這將是如下的明顯(對我來說)的方式:

src.collect { case countFoo: MyCount[IdentifierFoo] => countFoo } 

然而,這種失敗因爲Count的類型由於類型擦除而無法在運行時準確檢查:結果(錯誤地)得到所有Count s。我已經做了一件相當毛茸茸的東西:

src.collect { count => 
    count.id match { case IdentifierFoo => { 
    count match {case countFoo: MyCount[IdentifierFoo] => countFoo } 
} } } 

這個工程,但是很醜。我也嘗試匹配整個數如下:

src.collect { case countFoo: MyCount[IdentifierFoo](_: IdentifierFoo, _) => countFoo } 

...但是這似乎在斯卡拉2.10,這是我不得不到是無效的。有沒有更好的方式去做我想做的事情?

+1

選中此:https://meta.plasm.us/posts/2014/06/14/partitioning-by-constructor/ – 2015-04-03 03:39:09

回答

1

由於@mz提到,你是在結構上比類型匹配的更好,但是如果你想要得到的結果是List[MyCount[IdentifierFoo]]類型的,你要投值:

val list: List[MyCount[Identifier]] = List(MyCount(IdentifierFoo(1), 2), MyCount(IdentifierBar(2), 3), MyCount(IdentifierBar(3), 4)) 

list.collect{ case countFoo @ MyCount(_ : IdentifierFoo,_) => countFoo.asInstanceOf[MyCount[IdentifierFoo]]} 
res0: List[MyCount[IdentifierFoo]] = List(MyCount(IdentifierFoo(1),2)) 

list.collect{ case countFoo @ MyCount(_ : IdentifierBar,_) => countFoo.asInstanceOf[MyCount[IdentifierBar]]} 
res1: List[MyCount[IdentifierBar]] = List(MyCount(IdentifierBar(2),3), MyCount(IdentifierBar(3),4)) 
1

既然您有提取器IdentifierFooIdentifierBar並知道它們的結構,您可以使用它們。通過使用提取器,您不會完全匹配類型,所以我們可以避免類型擦除。

list.collect { case countFoo @ MyCount(IdentifierFoo(_), _) => countFoo } 

如:

sealed trait Identifier 
case class IdentifierFoo(id: Int) extends Identifier 
case class IdentifierBar(id: Int) extends Identifier 
case class MyCount[+T <: Identifier](id: T, count: Long) 
val list = List(MyCount(IdentifierFoo(1), 2), MyCount(IdentifierBar(2), 3), MyCount(IdentifierBar(3), 4)) 

scala> list.collect { case countFoo @ MyCount(IdentifierFoo(_), _) => countFoo } 
res142: List[MyCount[Product with Serializable with Identifier]] = List(MyCount(IdentifierFoo(1),2)) 

scala> list.collect { case countFoo @ MyCount(IdentifierBar(_), _) => countFoo } 
res143: List[MyCount[Product with Serializable with Identifier]] = List(MyCount(IdentifierBar(2),3), MyCount(IdentifierBar(3),4))