IterableFactoryDefaults
trait has the following definition:
trait IterableFactoryDefaults[+A, +CC[x] <: IterableOps[x, CC, CC[x]]] extends IterableOps[A, CC, CC[A @uncheckedVariance]] {
protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]): CC[A @uncheckedVariance] = iterableFactory.from(coll)
protected def newSpecificBuilder: Builder[A @uncheckedVariance, CC[A @uncheckedVariance]] = iterableFactory.newBuilder[A]
// overridden for efficiency, since we know CC[A] =:= C
override def empty: CC[A @uncheckedVariance] = iterableFactory.empty
}
As the doc says, this trait is used for providing default implementation of fromSpecific
and newSpecificBuilder
.
Regarding to this, I have the following questions:
Why does IterableFactoryDefaults
extend IterableOps
trait? To provide default implementation of those abstract methods, we can simply implement the following:
trait IterableFactoryDefaults[+A, +CC[x] <: IterableOps[x, CC, CC[x]]] {
def iterableFactory: IterableFactory[CC]
protected def fromSpecific(coll: IterableOnce[A @uncheckedVariance]): CC[A @uncheckedVariance] = iterableFactory.from(coll)
protected def newSpecificBuilder: Builder[A @uncheckedVariance, CC[A @uncheckedVariance]] = iterableFactory.newBuilder[A]
// overridden for efficiency, since we know CC[A] =:= C
override def empty: CC[A @uncheckedVariance] = iterableFactory.empty
}
Then plug the trait where it’s needed. Isn’t this design cleaner?
It seems that the purpose of IterableFactoryDefaults
extending IterableOps
is that it can be used alone to provide iterable operation methods. In other words, when implementing a collection satisfying CC[A] == C
, there’s no need to extends IterableOps[A, Coll, Coll[A]]
, we simply extends IterableFactoryDefaults[A, Coll]
and all iterable operations are available to the new type.
But if this is the idea, why we can see Iterable
actually extends both IterableOps
and IterableFactoryDefaults
? As in,
trait Iterable[+A] extends IterableOnce[A] with IterableOps[A, Iterable, Iterable[A]] with IterableFactoryDefaults[A, Iterable]
Why do we need Iterable
to inherit twice the same set of methods?