用于解构的Kotlin四倍,五倍等

ken*_*y_k 13 kotlin rx-java

我正在寻找一种干净的方式来在线创建可破坏的对象.kotlin.Pairkotlin.Triple涵盖了很多用例,但有时需要传递更多的对象.

一个示例用例是RX的zip函数,其中几个I/O调用的结果需要映射到另一个对象:

Single
    .zip(repositoryA.loadData(someId),
         repositoryB.loadData(someId),
         repositoryC.loadAll(),
         repositoryD.loadAll()),
         { objectA, objectB, objectsC, objectsD -> /*some Kotlin magic*/ }
    )
    .map { (objectA, objectB, objectsC, objectsD) -> /*do the mapping*/ }
Run Code Online (Sandbox Code Playgroud)

我想弄清楚"一些Kotlin魔法"部分会发生什么.如果只有3个存储库,那就是

Triple(objectA, objectB, objectsC)
Run Code Online (Sandbox Code Playgroud)

我是否需要为此创建一个新的数据类,以及任何n元组的情况,还是有另一种方法?

Dan*_*ugg 26

我发现只对所需的 n 元组进行代码生成最容易。用例是诸如记忆等功能的扩展方法。

data class NTuple2<T1, T2>(val t1: T1, val t2: T2)

data class NTuple3<T1, T2, T3>(val t1: T1, val t2: T2, val t3: T3)

data class NTuple4<T1, T2, T3, T4>(val t1: T1, val t2: T2, val t3: T3, val t4: T4)

data class NTuple5<T1, T2, T3, T4, T5>(val t1: T1, val t2: T2, val t3: T3, val t4: T4, val t5: T5)

data class NTuple6<T1, T2, T3, T4, T5, T6>(val t1: T1, val t2: T2, val t3: T3, val t4: T4, val t5: T5, val t6: T6)
Run Code Online (Sandbox Code Playgroud)

然后生成必要的构造助手:

infix fun <T1, T2> T1.then(t2: T2): NTuple2<T1, T2>
{
    return NTuple2(this, t2)
}

infix fun <T1, T2, T3> NTuple2<T1, T2>.then(t3: T3): NTuple3<T1, T2, T3>
{
    return NTuple3(this.t1, this.t2, t3)
}

infix fun <T1, T2, T3, T4> NTuple3<T1, T2, T3>.then(t4: T4): NTuple4<T1, T2, T3, T4>
{
    return NTuple4(this.t1, this.t2, this.t3, t4)
}

infix fun <T1, T2, T3, T4, T5> NTuple4<T1, T2, T3, T4>.then(t5: T5): NTuple5<T1, T2, T3, T4, T5>
{
    return NTuple5(this.t1, this.t2, this.t3, this.t4, t5)
}

infix fun <T1, T2, T3, T4, T5, T6> NTuple5<T1, T2, T3, T4, T5>.then(t6: T6): NTuple6<T1, T2, T3, T4, T5, T6>
{
    return NTuple6(this.t1, this.t2, this.t3, this.t4, this.t5, t6)
}
Run Code Online (Sandbox Code Playgroud)

所以我可以这样做:

val nTuple4 = 1 then 2 then "foo" then "bar"
Run Code Online (Sandbox Code Playgroud)

导致:

val nTuple4: NTuple4<Int, Int, String, String>
Run Code Online (Sandbox Code Playgroud)

  • 很好地使用中缀函数。尽管此时也可以定义一个重载的“tuple(..)”方法。重复的“then”使它显得有点长和冗长。 (2认同)

s1m*_*nw1 14

基本

让我们看看解构是如何工作的:

Kotlin为此定义了一个约定,即componentX() operator函数是Kotlin在许多地方使用的约定原则的一个例子.componentX()编译器使用这些函数来初始化解构声明中的变量.

例如,在Pair<A,B>这些函数中,如下所示:

operator fun component1(): A = first 

operator fun component2(): B = second
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样operators,是特殊处理的功能.这些componentX()函数可以由开发人员提供,并由编译器自动生成data类.顺便说Pair一下也是这样一个data班级.

回答

因此,data只要你需要的不仅仅是a ,请继续使用Triple.

例如,一个MultiComponent定义为这样的类:

data class MultiComponent(val x: Int, val y: Int, val z: Int, val a: Int, val b: Int, val c: Int)
Run Code Online (Sandbox Code Playgroud)

将被编译为具有函数component1(),, component2()... 的类,component6()并且可以在解构声明中使用:

val (q, w, e, r, t, z) = MultiComponent(1, 2, 3, 4, 5, 6)
Run Code Online (Sandbox Code Playgroud)

有关Kotlin约定和解构的更多详细信息,请参阅此博文(我的).


Tod*_*odd 9

与Scala相比,Kotlin对于高于3定义的值没有n元组.你已经正确识别Pair并且Triple.

根据这篇博客文章,Kotlin倾向于为这些用例使用数据类.所以是的,你必须定义一个数据类才能做你想做的事,没有Quadruple.我个人认为定义自己的数据类更加清晰,并且最终将被编译和使用与假设Quadruple无论如何相同的方式.

至于解构数据类,Kotlin也支持这一点:

data class Thingy(val a: String, val b: String, val c: String, val d: String)
val t = Thingy("A", "B", "C", "D")
val (aa, bb, cc, dd) = t
Run Code Online (Sandbox Code Playgroud)


Noe*_*lia 9

您可以将这些kotlin类添加到您的项目中,它们将完全一样工作,Pair或者Triple您将能够传递更多对象。

Quadruple(让你传递 4 个对象)

import java.io.Serializable

/**
 * Created by nalcalag on 09/02/2019.
 * 
 * Represents a quartet of values
 *
 * There is no meaning attached to values in this class, it can be used for any purpose.
 * Quadruple exhibits value semantics
 *
 * @param A type of the first value.
 * @param B type of the second value.
 * @param C type of the third value.
 * @param D type of the fourth value.
 * @property first First value.
 * @property second Second value.
 * @property third Third value.
 * @property fourth Fourth value.
 */
data class Quadruple<out A, out B, out C, out D>(
        val first: A,
        val second: B,
        val third: C,
        val fourth: D
) : Serializable {

    /**
     * Returns string representation of the [Quadruple] including its [first], [second], [third] and [fourth] values.
     */
    override fun toString(): String = "($first, $second, $third, $fourth)"
}

/**
 * Converts this quadruple into a list.
 */
fun <T> Quadruple<T, T, T, T>.toList(): List<T> = listOf(first, second, third, fourth)
Run Code Online (Sandbox Code Playgroud)

五元组(让你传递 5 个对象)

import java.io.Serializable

/**
 * Created by nalcalag on 09/02/2019.
 * 
 * Represents a quartet of values
 *
 * There is no meaning attached to values in this class, it can be used for any purpose.
 * Quadruple exhibits value semantics
 *
 * @param A type of the first value.
 * @param B type of the second value.
 * @param C type of the third value.
 * @param D type of the fourth value.
 * @param E type of the fifth value.
 * @property first First value.
 * @property second Second value.
 * @property third Third value.
 * @property fourth Fourth value.
 * @property fifth Fifth value.
 */
data class Quintuple<out A, out B, out C, out D, out E>(
        val first: A,
        val second: B,
        val third: C,
        val fourth: D,
        val fifth: E
) : Serializable {

    /**
     * Returns string representation of the [Quintuple] including its [first], [second], [third], [fourth] and [fifth] values.
     */
    override fun toString(): String = "($first, $second, $third, $fourth, $fifth)"
}

/**
 * Converts this quadruple into a list.
 */
fun <T> Quintuple<T, T, T, T, T>.toList(): List<T> = listOf(first, second, third, fourth, fifth)
Run Code Online (Sandbox Code Playgroud)