6

Das Merkmal TraversableLike[+A, +Repr] ermöglicht es, eine Sammlung zu erstellen, wobei einige Funktionen eine Repr zurückgeben, während andere weiterhin den Typ Parameter That auf die Funktion zurückgeben. Gibt es eine Möglichkeit, eine CustomCollection[A] zu definieren, in der Funktionen wie map, ++ und andere standardmäßig That als Repr werden, wenn nicht anders gedeutet?Erstellen Sie eine benutzerdefinierte Scala-Sammlung, in der standardmäßig die benutzerdefinierte Sammlung zurückgegeben wird?

Hier ist ein Code-Snippet, dass hoffentlich, was beschreibt Ich möchte:

case class CustomCollection[A](list: List[A]) extends TraversableLike[A, CustomCollection[A]] { 
    protected[this] def newBuilder = new CustomCollectionBuilder[A] 
    def foreach[U](f: (A) => U) {list foreach f} 
    def seq = list 
} 

class CustomCollectionBuilder[A] extends mutable.Builder[A, CustomCollection[A]] { 
    private val list = new mutable.ListBuffer[A]() 
    def += (elem: A): this.type = { 
    list += elem 
    this 
    } 
    def clear() {list.clear()} 
    def result(): CustomCollection[A] = CustomCollection(list.result()) 
} 

object CustomCollection extends App { 
    val customCollection = CustomCollection(List(1, 2, 3)) 
    println(customCollection filter {x => x == 1}) // CustomCollection(1) 
    println(customCollection map {x => x + 1}) // non-empty iterator 
} 

ich die letzte Zeile CustomCollection(2, 3, 4) sein möchte.

+0

ich nur +1 für seine nur drei Minuten hinter der Post om-nom-nom angemeldet. Es scheint keine "rechtzeitige Bearbeitung" zu geben. Knopf mit einem Daumen hoch Logo. –

Antwort

4

Sie benötigen einen Begleiter Objekt, das die raffinierte CanBuildFrom Instanz bietet einzurichten:

import collection.TraversableLike 
import collection.generic.{CanBuildFrom, GenericCompanion, GenericTraversableTemplate, 
    TraversableFactory} 
import collection.mutable.{Builder, ListBuffer} 

object CustomCollection extends TraversableFactory[CustomCollection] { 
    def newBuilder[A] = new CustomCollectionBuilder[A] 
    implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, CustomCollection[A]] = 
    new CanBuildFrom[Coll, A, CustomCollection[A]] { 
     def apply(): Builder[A, CustomCollection[A]] = new CustomCollectionBuilder() 
     def apply(from: Coll): Builder[A, CustomCollection[A]] = apply() 
    } 
} 
case class CustomCollection[A](list: List[A]) extends Traversable[A] 
with TraversableLike[A, CustomCollection[A]] 
with GenericTraversableTemplate[A, CustomCollection] { 
    override def companion: GenericCompanion[CustomCollection] = CustomCollection 
    def foreach[U](f: A => U) { list foreach f } 
    override def seq = list 
} 

class CustomCollectionBuilder[A] extends Builder[A, CustomCollection[A]] { 
    private val list = new ListBuffer[A]() 
    def += (elem: A): this.type = { 
    list += elem 
    this 
    } 
    def clear() {list.clear()} 
    def result(): CustomCollection[A] = CustomCollection(list.result()) 
} 

val customCollection = CustomCollection(List(1, 2, 3)) 
val f = customCollection filter {x => x == 1} // CustomCollection[Int] 
val m = customCollection map {x => x + 1}  // CustomCollection[Int] 
+0

Große Antwort! Ich hatte das Gefühl, dass ich ein cbf benutzen musste, aber ich konnte nicht den allgemeinsten Weg finden, es zu tun. Gibt es irgendwo, wo ich mehr über die Besonderheiten der Sammlungen api lesen kann? I.e. Wie soll ich wissen, dass ich neben "TraversableLike" auch "GenericTraversableTemplate" erweitern muss? –

+0

@ dicarlo2 - Ich sehe im Allgemeinen den Quellcode der Klasse am ähnlichsten zu dem, was ich mache und kopieren, was sie gemischt. Ich habe dies zuverlässiger als jeder andere Ansatz in der Abwesenheit von genau zu wissen, welche Funktionalität zur Verfügung gestellt wird nach jedem Merkmal (und wie Sie wollen, dass sich alle Vererbungsmuster in Diamantform auflösen). –

+0

@RexKerr Heh, das ist das Gleiche, was ich normalerweise mache, nachdem ich die Frage gestellt habe, dass ich bis "TraversableFactory" gekommen bin, bevor ich vom Computer weg musste, immer noch wer weiß, wie viele Dateien ich durchgesehen hätte diamantförmige Vererbungsmuster. Schade, es gibt keine bessere Referenz und die Dokumentation beleuchtet nicht immer die Beziehungen zwischen den einzelnen Merkmalen. –

Verwandte Themen