扩展Scala集合

时间:2011-01-29 21:30:26

标签: scala scala-collections

我想派生一个Scala内置集合的版本,该集合扩展了特定泛型类型的功能,例如,

import scala.collection.immutable._
class Tuple2Set[T1,T2] extends HashSet[Tuple2[T1,T2]] {
 def left = map ( _._1 )
 def right = map ( _._2 )
}

但是,当我尝试将其与以下测试一起使用时

  new Tuple2Set[String,String]() + (("x","y")) left

我收到以下编译错误

error: value left is not a member of scala.collection.immutable.HashSet[(String, String)]

如何更改课程以使其有效?

4 个答案:

答案 0 :(得分:7)

您确定需要扩展Scala集合吗?要使上面的代码工作,您可以这样做:

class Tuple2Set[T1,T2](set: Set[(T1, T2)]) {
  def left = set map ( _._1 )
  def right = set map ( _._2 )
}

implicit def toTuple2Set[T1, T2](set: Set[(T1, T2)]) = new Tuple2Set(set)

Set[(String, String)]() + (("x","y")) left

在这种情况下,Tuple2Set只是任何其他Set实现的包装器。这意味着您不再受HashSet的限制,您的方法leftright也可用于任何其他实现(如TreeSet)。

我认为在大多数情况下,包装或组合+委派比继承更好(并且导致更少的问题)。

答案 1 :(得分:4)

正如 Kevin Wright 所说,+操作将返回HashSet。类型类CanBuildFrom用于在map等操作期间构建新集合。因此,如果您希望+返回Tuple2Set而不是HashSet,那么您应该实现CanBuildFrom并在协同对象中隐式提供它,如下所示:

object Tuple2Set {
    implicit def canBuildFrom[T1, T2] = 
        new CanBuildFrom[Tuple2Set[T1, T2], (T1, T2), Tuple2Set[T1, T2]] {...}
}

答案 2 :(得分:4)

您的问题的一般答案在这里有点过于复杂。但它已经写在一些web pages中。

具有更多背景的相同材料也出现在我们的书“Scala编程”,Artima Press的第2版中。

答案 3 :(得分:0)

您的示例不起作用的原因是+操作的返回类型是HashSet而不是Tuple2Set

使用“pimp my library”模式而不是继承,你会有更多的运气。