我已经创建了一个辅助方法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
}
Run Code Online (Sandbox Code Playgroud)
实施例
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"))
Run Code Online (Sandbox Code Playgroud)
实现输出示例
@JvmStatic fun main(args: Array<String>) {
var first = createPersonChain()
// first.name = "Bob"
// first.next.name = "Bitzy"
// first.next.next.name = "Blitzy"
}
Run Code Online (Sandbox Code Playgroud)
是否有一个functional或simpler用于acheiving的方式code上面保持implementaion用法一样吗?
功能性成语折叠很适合您的需求:它采用初始项目,然后迭代其他项目,保持累积值,使用您提供的功能更新每个正在处理的项目.
在科特林,它是fold扩展功能的Iterable,Sequence或Array.
您可以通过以下方式使用它:
fun <T : Chain<T>> buildChain(first: T, vararg members: T): T {
members.fold(first as T?) { acc, i -> acc?.let { it + i } }
return first
}
Run Code Online (Sandbox Code Playgroud)
这里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 }
Run Code Online (Sandbox Code Playgroud)
而且有reduce与reduceRight类似的语义,但是使用第一和最后一个项目分别累加器的初始值.这是以下示例reduceRight:
fun <T : Chain<T>> buildChain(first: T, vararg members: T): T? =
(listOf(first) + members).reduceRight { i, acc -> i.apply { plus(acc) } }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1789 次 |
| 最近记录: |