2016-03-05 12 views
5

Stworzyłem metody pomocnika buildChain który zasadniczo tworzy łańcuch obiektów podanych że implementować interfejs IChain<T> i ustawić umów next członekprostsze lub bardziej funkcjonalny sposób łączenia obiektów w Kotlin

Kodeks

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 
} 

przykładów realizacji

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")) 

Przykâadowa implementaion

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

Czy istnieje functional lub simpler sposób acheiving się code powyżej utrzymując zużycie implementaion samo?

Odpowiedz

8

Funkcjonalny idiom fold dobrze pasuje do Twoich potrzeb: zajmuje początkowy element, a następnie przechodzi do kolejnych pozycji, zachowując skumulowaną wartość, która jest aktualizowana dla każdego przedmiotu przetwarzanego za pomocą funkcji, którą podajesz.

W Kotlin jest to fold extension function dla Iterable, Sequence lub Array.

Można go używać w następujący sposób:

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

Tutaj first as T? obsada jest potrzebne dla danego typu akumulatora należy wnioskować jako wartości pustych T?, ponieważ plus w swoim Chain<T> zwraca wartość pustych (nawiasem mówiąc, jest to konieczne?).

Można również użyć foldRight, który zaledwie iteracje w odwrotnej kolejności:

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 } 

i istnieje reduce i reduceRight o podobnej semantyki, lecz stosując pierwszy i ostatni element odpowiednio dla wartości początkowej akumulatorze jest. Oto przykład z reduceRight:

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

Dzięki skrótowi działa jak urok, zabawne jest to, że właśnie nauczyłem się funkcji składania w ciągu dnia i nie zdawałem sobie sprawy, że można go użyć w połączeniu z łańcuchem kodu –

0

Spróbuj apply{}. W bloku {} twoje metody są oddzielone przez ';'

Object().apply{ method1(); signUp(user) }