This is a follow-up on the below question: How to create a custom collection that extends on Sets In Scala?
I have a basic class that extends on the Set
collection and most of the functions like filter
, collect
and others are working :
import scala.collection._
class TestSet[A]
extends mutable.Set[A]
with mutable.SetOps[A, mutable.Set, TestSet[A]] {
private var data = mutable.Set.empty[A]
override protected def fromSpecific(coll: IterableOnce[A]): TestSet[A] = TestSet.from(coll)
override protected def newSpecificBuilder: mutable.Builder[A, TestSet[A]] = TestSet.newBuilder
override def empty: TestSet[A] = TestSet.empty
override def clear(): Unit = {
data = mutable.Set.empty
}
override def subtractOne(elem: A): TestSet.this.type = {
data -= elem
this
}
override def addOne(elem: A): TestSet.this.type = {
data = elem
this
}
override def contains(elem: A): Boolean = data.contains(elem)
override def iterator: Iterator[A] = {
data.iterator
}
}
object TestSet {
def empty[A] = new TestSet[A]
def from[A](source: IterableOnce[A]): TestSet[A] =
source match {
case pm: TestSet[A] => pm
case _ => (newBuilder = source).result()
}
def apply[A](elem: A*): TestSet[A] = from(elem)
def newBuilder[A]: mutable.Builder[A, TestSet[A]] =
new mutable.GrowableBuilder[A, TestSet[A]](empty)
import scala.language.implicitConversions
implicit def toFactory[A](self: this.type): Factory[A, TestSet[A]] =
new Factory[A, TestSet[A]] {
def fromSpecific(it: IterableOnce[A]): TestSet[A] = self.from(it)
def newBuilder: mutable.Builder[A, TestSet[A]] = self.newBuilder
}
}
It might not be possible but I originally wanted SetOps with the following types mutable.SetOps[A, TestSet, TestSet[A]]
instead of mutable.SetOps[A, mutable.Set, TestSet[A]]
, but I am having trouble redefining iterableFactory
.
A working snippet can be found here: https://scastie.scala-lang.org/4Qi8ZueDTpScDwxDfqptew
CodePudding user response:
The scaladoc of IterableFactory
says "Base trait for companion objects..." which is a hint that the companion of your TestSet
should implement that trait.
All you need to do is add...
object TestSet extends IterableFactory[TestSet] {
// ...
}
...and then remove your def apply[A](elem: A*): TestSet[A]
from the companion (because that is already inherited from IterableFactory
).
Then you'd do the following in your class:
class TestSet[A]
extends mutable.Set[A]
with mutable.SetOps[A, TestSet, TestSet[A]] {
// ...
// returns your companion object
override def iterableFactory: IterableFactory[TestSet] = TestSet
// ...
}
And that's all it would need.
(This is so simple because you already implemented all abstract members of IterableFactory[TestSet]
in your companion object - it would not work if the companion were empty.)