Расширьте Набор Скала с конкретным типом - PullRequest
3 голосов
/ 11 декабря 2010

Действительно трудно понять, как расширить неизменяемый набор с помощью класса, который будет представлять набор конкретного типа.Я делаю это, чтобы попытаться создать хороший DSL.

Я хотел бы иметь класс Thing, и когда вы добавляете «вещи» вместе, вы получаете объект ThingSet, который расширяет Set.

class Thing(val name:String){
  def +(other: Thing):ThingSet = new ThingSet() + other
}

Я просто не могу понять, как создать объект ThingSet.Я знаю, что мне нужно смешивать такие черты, как GenericSetTemplate, SetLike и т. Д. Но я просто не могу заставить его работать.

Пожалуйста, кто-нибудь может дать мне несколько советов, так как я не могу найти что-то достаточно ясное для изученияот.Я попытался посмотреть на реализации BitSet и HashSet, но заблудился.

Ответы [ 2 ]

9 голосов
/ 14 декабря 2010

Адаптация от этого поста Daily Scala , а также источника к BitSet, что является прекрасным примером здесь, потому что это не параметризованная коллекция, а довольно короткая и простая.

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
    }
}
3 голосов
/ 14 декабря 2010

Из скаладоков на Сете, я думаю, вам просто нужно реализовать 4 или 5 методов.В этом случае я решил использовать поддержку Seq [Thing] для создания моей фактической реализации набора.

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"))

в результате:Запустите это в файле сценария, а не в REPL из-за циклической зависимости между Thing и ThingSet.

...