what is the difference between a "trait" and a "template trait"?
Looking at the scaladoc for Traversable and TraversableLike, I'm having a hard time figuring out wh开发者_JAVA百科at the difference between them is (except that one extends the other). The only apparent difference in the documentation is that it says Traversable is a "trait" and TraversableLike is a "template trait". But googling for "template trait" does not reveal a definition for this term. Help!
I haven't seen this terminology in general use in Scala, and I think it's specific to the design of the Scala collections API. You can learn more by reading The Architecture of Scala Collections (especially the section on "factoring out common operations")[1] and the Scala collections SID. §4.2 of the SID is relevant, although they're referred to as "implementation traits" there:
Collection classes such as Traversable or Vector inherit all their concrete method implementations from an implementation trait. These traits are named with the Like suffix; for instance VectorLike is the implementation trait for Vector and TraversableLike is the implementation trait for Traversable.
In short, their purpose is both to separate implementation for use outside the collections hierarchy (e.g. StringOps
extends TraversableLike
but not Traversable
) and to factor out common operations in such a way that the collection type is preserved (see IttayD's answer for a more thorough explanation).
I should note that you really don't need to be concerned with these classes unless you are extending the collections hierarchy. For ordinary use, focus on the Traversable
, Iterable
, Seq
, etc. traits. If you're new to the Scala Collections API, I would suggest starting with the Scala 2.8 Collection API document, then reference the scaladoc as necessary. You can't expect to get the 'big picture' looking through the scaladoc.
[1] credit goes to michid for this link
The XXXLike traits have an important role of adding the Repr generic parameter. Methods that are supposed to return the same collection type, like filter, map, flatMap, are implemented in low level traits (TraversableLike). To encode their return type, those traits receive it:
trait TraversableLike[+A, +Repr] ...
...
def filter(p: A => Boolean): Repr = {
(for map and flatMap the issue is more complicated, I won't go into it here)
Now say you have a new type of collection. You could do:
trait MyCollection[+A] extends TraversableLike[A, MyCollection]
But then if anyone wants to extend your collection, they are stuck with return values of MyCollection from the various inherited methods.
So instead, you create:
trait MyCollectionLike[+A, +Repr] extends TraversableLike[A, Repr]
and
trait MyCollection[+A] extends MyCollectionLike[A, MyCollection]
and anyone that wants to extend your collection extends MyCollectionLike
The [...]Like classes are implementation classes for the actual collection classes. In a sense they act like template implementations from which most - if not all - behavior is inherited by the actual collection classes.
For a very detailed and approachable overview read The Architecture of Scala Collections.
精彩评论