用混凝土类型扩展Scala集

用混凝土类型扩展Scala集,scala,scala-2.8,Scala,Scala 2.8,真的很难用一个表示一组具体类型的类来扩展不可变集。我这样做是为了尝试创建一个好的DSL 我想要一个类的东西,当你们把“东西”加在一起,你们会得到一个ThingSet对象,它扩展了集合 class Thing(val name:String){ def +(other: Thing):ThingSet = new ThingSet() + other } 我就是搞不懂如何制作ThingSet对象。我知道我需要混合一些特性,比如GenericSetTemplate、SetLike等,但我就是不

真的很难用一个表示一组具体类型的类来扩展不可变集。我这样做是为了尝试创建一个好的DSL

我想要一个类的东西,当你们把“东西”加在一起,你们会得到一个ThingSet对象,它扩展了集合

class Thing(val name:String){
  def +(other: Thing):ThingSet = new ThingSet() + other
}
我就是搞不懂如何制作ThingSet对象。我知道我需要混合一些特性,比如GenericSetTemplate、SetLike等,但我就是不能让它起作用


拜托,谁能给我一些建议,因为我找不到足够明确的东西来学习。我已经试过查看位集和哈希集的实现,但是没有找到。

从scaladocs on Set开始,我认为您只需要实现4或5个方法。在本例中,我决定使用backing Seq[Thing]来创建实际的set实现

class ThingSet(things: Seq[Thing]) extends Set[Thing] {
  def contains(key: Thing) = { things.contains(key) }
  def iterator: Iterator[Thing] = { things.iterator }
  def +(elem: Thing) = new ThingSet(things :+ elem)
  def -(elem: Thing) = new ThingSet(things.filterNot(_ == elem))
  override def empty = new ThingSet(Nil)
}

class Thing(val name: String) {
  def +(other: Thing) = { new ThingSet(List(this,other)) }
  override def toString = name
}

val thing = new Thing("I'm a new thing")
println(thing + new Thing("I'm some other thing"))
结果:

Set(I'm a new thing, I'm some other thing)
注意:我认为您必须在脚本文件而不是REPL中运行此操作,因为Thing和ThingSet之间存在周期性依赖关系。

从post以及源代码调整到
位集,这是一个很好的示例,因为它不是一个参数化的集合,并且非常简短

import scala.collection.SetLike
import scala.collection.generic.{GenericSetTemplate, GenericCompanion, CanBuildFrom}
import scala.collection.mutable.{Builder, SetBuilder}

class ThingSet(seq : Thing*) extends Set[Thing] 
                             with SetLike[Thing, ThingSet]
                             with Serializable {
    override def empty: ThingSet = new ThingSet()
    def + (elem: Thing) : ThingSet = if (seq contains elem) this 
        else new ThingSet(elem +: seq: _*)
    def - (elem: Thing) : ThingSet = if (!(seq contains elem)) this
        else new ThingSet(seq filterNot (elem ==): _*)
    def contains (elem: Thing) : Boolean = seq exists (elem ==)
    def iterator : Iterator[Thing] = seq.iterator
}

object ThingSet {
    def empty: ThingSet = new ThingSet()
    def newBuilder: Builder[Thing, ThingSet] = new SetBuilder[Thing, ThingSet](empty)
    def apply(elems: Thing*): ThingSet = (empty /: elems) (_ + _)
    def thingSetCanBuildFrom = new CanBuildFrom[ThingSet, Thing, ThingSet] {
        def apply(from: ThingSet) = newBuilder
        def apply() = newBuilder
    }
}

好。。。您忘了将
添加到
内容集
,因此可能需要修复该错误。:-)我实现的Set方法与前两个方法不同。您引用的是什么操作?像
map
filter
之类的方法。这是错误的实现,我意外地+1e了它。它不遵守集合的规则。生成与原始集合不同的重复元素newthingset(Seq(newthing(“dog”)、newthing(“cat”)、newthing(“dog”))res1:ThingSet=set(dog、cat、dog)set(“dog”、“cat”、“dog”)res2:scala.collection.immutable.set[String]=set(dog、cat)