我想派生一个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)]
如何更改课程以使其有效?
答案 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
的限制,您的方法left
和right
也可用于任何其他实现(如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”模式而不是继承,你会有更多的运气。