0

可以说我有一个List[TraitA]对象。TraitA提供了一个属性propX : String。我知道这个列表的一个子集也是 的一个实例TraitB,但是它不提供属性propX

例如:

trait TraitA
{
  def propX : String
}

trait TraitB
{
  def abc : Int
}

列表中的一些实例只是extend TraitA,而另一些extend TraitA with TraitB。我只需要提取那些具有TraitB但我需要保留属性propX的实例TraitApropX只能是几个值,我需要的是根据这个值Map对实例进行分组。TraitB

所以我需要TraitBList[TraitA]实例中提取这个实​​例子集,因为其中一些是TraitA with TraitB,并创建一个Map[String, List[TraitB]],其中密钥propX来自TraitA

我一直在摆弄for理解,但由于某种原因,我不能yielda List[(String, TraitB)]of tuples (那时我可以groupBy _.1),可能是因为第一个生成器是 type TraitA

我试过这个,但它抱怨预期的类型是List[(String, TraitA)]

for {
traitA <- listOfTraitAs
traitBoption = (traitA match {
    case traitB : TraitB => Some(traitB)
    case _ => None
   })
} yield (traitA.propX, traitBoption)

另一方面,如果我filter通过模式匹配列出我在过滤功能中TraitB失去可见性。propX

实现这一目标的最佳方法是什么?

4

1 回答 1

2

我不明白为什么filter不适合你:

scala> trait TraitA { def propX: String }; trait TraitB { def abc: Int }
defined trait TraitA
defined trait TraitB

scala> class A extends TraitA { def propX = util.Random.nextInt(5).toString() }
defined class A

scala> class B extends A with TraitB { def abc = util.Random.nextInt(5) }
defined class B

scala> val xs: List[TraitA] = List.fill(15)(if (util.Random.nextBoolean()) new A else new B)
xs: List[TraitA] = List(A@6b46e91a, B@7c71e0fb, A@1869be91, B@465e2e1c, B@5125545b, A@69c54bfb, B@17ff81fd, A@7af155a, B@77a2cba6, A@60e83ca6, A@2ee5e7fe, B@77e1ecbf, A@117e2d16, A@72c20852, B@20b07a5a)

scala> xs collect { case a: TraitB => a } groupBy (_.propX)
res7: scala.collection.immutable.Map[String,List[TraitA with TraitB]] = Map(4 -> List(B@465e2e1c, B@77e1ecbf), 1 -> List(B@77a2cba6), 0 -> List(B@20b07a5a), 2 -> List(B@7c71e0fb, B@17ff81fd), 3 -> List(B@5125545b))

即使您失去了可见性,您也可以始终使用类似{ case a: TraitA with TraitB => }.

于 2014-02-15T03:16:27.990 回答