2013-05-29 10 views
8

Wie der Titel dieser Frage suggeriert: meine Frage ist mehr über Form (idiomatische Konvention) als Funktion. Setzen Kurz und bündig:Idiomatic Scala: Semantischer Unterschied zwischen <Collection> Like und <Collection> Typen?

Was ist der semantische Unterschied zwischen MyCollectionLike und MyCollection?

Als Beispiele: Was ist der Unterschied zwischen StringLike und String oder MapLike und Map. Bei genauerer Betrachtung der Scala-API-Dokumente kann ich feststellen, dass XLike normalerweise ein Super-Typ von X ist. Aber darüber hinaus ist mir der semantische Unterschied zwischen diesen Schichten der Abstraktion nicht klar.

In der Praxis, wenn ich eine neue Klasse/Eigenschaft erstellen würde, würde das Verständnis dieser Unterscheidung hilfreich sein, wenn ich Namen für diese Klasse wähle.

Mein besonderes Problem, wo diese nach oben gekommen ist wie folgt:

ich das Merkmal erstellt werden soll: SurjectiveMap[K, T] die gemischt-in werden kann entweder mit Map[K, Set[T]] oder MapLike[K, SetLike[T]]. Da ich den semantischen Unterschied zwischen *Like und * nicht kenne, bin ich mir nicht sicher, wohin ich gehen soll.

Antwort

3

Der gleiche Unterschied wie zwischen IFoo und Foo, Bar und BarImpl (mit Ausnahme der Tatsache, dass TraversableLike super-Merkmal ist die Implementierung enthält):

Die Scala Sammlung Bibliothek Code-Duplizierung vermieden und erreicht die "self-result-type" -Prinzip durch Verwendung von generischen Buildern und Traversalen über Sammlungen in sogenannten Implementierungsmerkmalen. Diese Merkmale sind benannt mit einem Like-Suffix; Zum Beispiel ist IndexedSeqLike das Implementierungsmerkmal für IndexedSeq, und ähnlich ist TraversableLike das Implementierungsmerkmal für Traversable. Collection-Klassen wie Traversable oder IndexedSeq erben alle ihre konkreten Methoden Implementierungen von diesen Merkmalen.

von Scala collections architecture

1

Ich denke, mit den Like Züge können Sie die Rückkehr (Darstellung) Typen verfeinern. Dies erfordert viel mehr Arbeit. Vergleichen:

import collection.generic.CanBuildFrom 

object FooMap { 
    type Coll = FooMap[_, _] 
    implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), FooMap[A, B]] = ??? 
} 
trait FooMap[A, +B] extends Map[A, B] { 
    def foo = 33 
} 

def test(f: FooMap[Any, Any]) { 
    f.map(identity).foo // nope, we ended up with a regular `Map` 
} 

gegen

object FooMap extends collection.generic.ImmutableMapFactory[FooMap] { 
    override type Coll = FooMap[_, _] 
    implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), FooMap[A, B]] = ??? 
    def empty[A, B]: FooMap[A, B] = ??? 
} 
trait FooMap[A, +B] extends Map[A, B] 
    with collection.immutable.MapLike[A, B, FooMap[A, B]] { 

    def foo = 33 
    override def empty: FooMap[A, B] = FooMap.empty[A, B] 
} 

def test(f: FooMap[Any, Any]) { 
    f.map(identity).foo // yes 
} 

Die MapLike Eigenschaft nach dem Map Merkmal in gemischt werden müssen für die richtigen Rückgabetypen treten


Noch Sie nicht bekommen. Alles umsonst scheint es, zB Sie müssen mehr Methoden überschreiben:

override def +[B1 >: B](kv: (A, B1)): FooMap[A, B1] // etc.