在Kotlin中链接对象的更简单或更实用的方法

时间:2016-03-05 17:21:48

标签: kotlin

我创建了一个辅助方法buildChain,它基本上创建了一个 给定它们实现接口IChain<T>的对象链 并设置合同next成员

守则

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
}

实施示例

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

实施输出示例

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

是否有functionalsimpler方法可以实现上述code保持实施用途相同的方式?

2 个答案:

答案 0 :(得分:9)

功能idiom fold非常适合您的需求:它接受一个初始项目,然后迭代其他项目,维护一个累计值,该值在您使用您提供的功能处理的每个项目上更新。

在Kotlin中,IterableSequenceArrayfold extension function

您可以通过以下方式使用它:

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

此处需要first as T?强制转换才能将累加器类型推断为可为空T?,因为plus中的Chain<T>会返回可为空的值(顺便说一句,是吗?必要?)。

您也可以使用foldRight,它只是以相反的顺序迭代:

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 }

并且reducereduceRight具有相似的语义,但分别使用第一个和最后一个项作为累加器的初始值。以下是reduceRight的示例:

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

答案 1 :(得分:2)

试试apply{}。在{}块传递中,您的方法用&#39;;&#39;

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