【问题标题】:Simpler or more functional way of chaining objects in Kotlin在 Kotlin 中链接对象的更简单或更实用的方法
【发布时间】:2016-03-05 17:21:47
【问题描述】:

我创建了一个辅助方法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 并保持实现使用相同?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    函数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&lt;T&gt; 返回可空值(顺便说一句,有必要吗?)。

    你也可以使用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) } }
    

    【讨论】:

    • 感谢热键的作用就像一个魅力,有趣的是我今天刚学会折叠功能,并没有意识到它可以与链接代码结合使用
    【解决方案2】:

    试试apply{}。在{} 块中传递你的方法,用';'分隔

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

    【讨论】:

      猜你喜欢
      • 2016-11-14
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多