2016-03-05 10 views
5

ich eine Hilfsmethode buildChain erstellt haben, die im wesentlichen eine Kette von Objekten schafft gegeben, dass sie die Schnittstelle IChain<T> und stellen Sie die Verträge next MitgliedSimpler oder mehrere funktionelle Art und Weise Objekte in Kotlin von Verkettungs

Der Kodex umzusetzen

interface Chain<T> { 
    var next: T? 

    operator fun plus(next: T): T? 
} 

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T { 
    var next: T? = null 
    members.forEachIndexed { i, t -> 
     if (i == 0) { 
      next = first + t 
     } else { 
      next = next?.run { this + t } 
     } 
    } 
    return first 
} 

Implementierung Beispiel

data class Person(val name: String) : Chain<Person> { 
    override var next: Person? = null 

    override fun plus(next: Person): Person? { 
     this.next = next 
     return next 
    } 
} 

fun createPersonChain() 
     = buildChain(Person("Bob"), Person("Bitzy"), Person("Blitzy")) 

implementaion Ausgabebeispiel

@JvmStatic fun main(args: Array<String>) { 
    var first = createPersonChain() 
    // first.name = "Bob" 
    // first.next.name = "Bitzy" 
    // first.next.next.name = "Blitzy" 
} 

Gibt es eine functional oder simpler Weg, um die code oben halten die implementaion Nutzung das gleiche für Acheiving?

Antwort

8

eine funktionelle idiom fold zu Ihren Ansprüchen passt gut: es nimmt einen Anfangspunkt und wiederholt sich dann über die anderen Elemente, um einen akkumulierten Wert gehalten wird, die mit der Funktion die Sie auf jedes Element, das verarbeitet wird aktualisiert.

In Kotlin ist es fold extension function für Iterable, Sequence oder Array.

Sie können auf folgende Weise verwenden:

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T { 
    members.fold(first as T?) { acc, i -> acc?.let { it + i } } 
    return first 
} 

Hier first as T? Guss ist für den Speichertyp benötigt, um als Nullable-T? geschlossen werden, weil plus in Ihrem Chain<T> kehrt Nullable-Wert (übrigens ist es notwendig?).

Sie auch foldRight verwenden können, die gerade iteriert in umgekehrter Reihenfolge:

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T? = 
     (listOf(first) + members) 
      .foldRight(null as T?) { i, acc -> acc?.let { i + acc }; i } 

Und es gibt reduce und reduceRight mit ähnlicher Semantik, aber das ersten und das letzte Element mit jeweils für den Anfangswert des Akkumulators. Hier ist das Beispiel mit reduceRight:

fun <T : Chain<T>> buildChain(first: T, vararg members: T): T? = 
     (listOf(first) + members).reduceRight { i, acc -> i.apply { plus(acc) } } 
+0

Dank Hotkey funktioniert wie ein Charme, lustige Sache ist, ich habe gerade die Faltfunktion im ganzen heute gelernt und wusste nicht, es könnte in Kombination mit dem Chaining-Code verwendet werden –

0

apply{} Versuchen. In der {} Block übergeben Sie Ihre Methoden getrennt mit ';'

Verwandte Themen