First of all, having a default (zero) value for someProperty
makes things a bit easier. In your case, I guess you could choose Must
or MustNot
, depending on the specifics of your problem.
I'll assume the following definition of T
and its default:
sealed trait T
object T {
final val Default: T = Must
}
case object Must extends T
case object MustNot extends T
case object Should extends T
You can have the following implementation for MySet
, deferring most operations to its set
attribute, and some to its companion object. Also, note that some methods like filter
don't use CanBuildFrom
, so you have to override newBuilder
method for them.
class MySet[A](val someProperty: T, set: Set[A])
extends Set[A] with SetLike[A, MySet[A]] {
def +(elem: A): MySet[A] = new MySet[A](someProperty, set + elem)
def -(elem: A): MySet[A] = new MySet[A](someProperty, set - elem)
def contains(elem: A): Boolean = set contains elem
def iterator: Iterator[A] = set.iterator
override def companion = MySet
override def empty: MySet[A] = MySet.empty[A]
// Required for `filter`, `take`, `drop`, etc. to preserve `someProperty`.
override def newBuilder: mutable.Builder[A, MySet[A]] =
MySet.newBuilder[A](someProperty)
}
As for the companion object MySet
, it's possible to extend SetFactory[MySet]
or some other base class of collection companion objects. This gives implementations of MySet.empty[A]
and MySet.apply[A](as: A*)
, which create MySet
using the default value of someProperty
.
object MySet extends SetFactory[MySet] {
// For the builder you can defer to the standard `mutable.SetBuilder`
class MySetBuilder[A](someProperty: T) extends
mutable.SetBuilder[A, MySet[A]](new MySet(someProperty, Set.empty))
def newBuilder[A] = newBuilder[A](T.Default)
// Additional method for creating a builder with a known value of `someProperty`
def newBuilder[A](someProperty: T) = new MySetBuilder[A](someProperty)
// You may also want to define `apply` and `empty` methods
// that take a known `someProperty`.
// `CanBuildFrom` from `MySet[_]` to `MySet[A]`.
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, MySet[A]] =
new CanBuildFrom[Coll, A, MySet[A]] {
// This is the method that makes
// e.g. `map`, `flatMap`, `collect` preserve `someProperty`
def apply(from: Coll): mutable.Builder[A, MySet[A]] =
newBuilder[A](from.someProperty)
def apply(): mutable.Builder[A, MySet[A]] = newBuilder[A]
}
}