Extending Scala collections

让人想犯罪 __ 提交于 2019-12-04 04:30:07

问题


I would like to derive a version of a Scala built-in collection that expands on the functionality for a particular generic type e.g.,

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

However when I try to use it with the following test

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

I get the following compile error

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

How can I change the class so that this works?


回答1:


As Kevin Wright said, + operation will return back HashSet. Type class CanBuildFrom is used to build new collections during operations like map. So if you want + to return Tuple2Set instead of HashSet you should implement CanBuildFrom and make it implicitly available in companion object like this:

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



回答2:


Are you sure you really need to extend Scala collection? To make the code above work you can do this:

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

In this case Tuple2Set is just the wrapper for any other Set implementations. This means you are not limited to HashSet anymore and your methods left and right will be available on any other implementations as well (like TreeSet).

I think in most cases wrapping or composition+delegation works much better than inheritance (and causes less problems).




回答3:


The general answer to your question is a bit too involved for a response here. But it has been written up in some web pages.

The same material with more context is also in the 2nd edition of our book, Programming in Scala, Artima Press.




回答4:


The reason your example doesn't work is that the return type of the + operation is a HashSet and not a Tuple2Set.

You'll have much more luck using the "pimp my library" pattern instead of inheritance.



来源:https://stackoverflow.com/questions/4839566/extending-scala-collections

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!