2010-12-11 2 views
0

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

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

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

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

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

+0

Ну ... вы забыли добавить 'this' в' ThingSet', чтобы вы могли исправить эту ошибку. :-) –

ответ

7

Адаптация от this 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

Из скаладоков на наборе, я думаю, вам просто нужно реализовать 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")) 

приводит:

Set(I'm a new thing, I'm some other thing) 

примечание: Я думаю, что вы должны запустить это в файл сценария, а не РЕПЛ из-за циклической зависимости между Thing и ThingSet.

+1

Этот 'ThingSet' не будет возвращать' ThingSet' при манипуляции. –

+0

Используемые методы Set, за исключением первых двух. С какими манипуляциями вы ссылаетесь? – Collin

+0

Методы типа 'map' или' filter'. –

Смежные вопросы