破壊可能なオブジェクトをインラインで作成するクリーンな方法を探しています。 kotlin.Pair
およびkotlin.Triple
は多くのユースケースをカバーしますが、渡される必要のあるオブジェクトがさらにある場合があります。
使用例の1つは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*/ }
私は「コトリンの魔法」の部分で何が起こるかを理解しようとしています。リポジトリが3つしかない場合は、
Triple(objectA, objectB, objectsC)
このため、およびn-Tupleの場合のために新しいデータクラスを作成する必要がありますか、それとも別の方法がありますか?
destructuringがどのように機能するか見てみましょう:
Kotlinはこのための規則を定義しています。つまり、componentX()
operator
関数は、多くの場所でKotlinで使用される規則の原則の例です。これらのcomponentX()
関数は、宣言の構造化解除で変数を初期化するためにコンパイラーによって使用されます。
たとえば、_Pair<A,B>
_では、これらの関数は次のようになります。
_operator fun component1(): A = first
operator fun component2(): B = second
_
ご覧のとおり、これらは operators
、特別に処理された関数です。これらのcomponentX()
関数は開発者が提供でき、data
クラスのコンパイラーによって自動的に生成されます。 Pair
もそのようなdata
クラスです。
したがって、data
以上のものが必要な場合は、先に進んでTriple
クラスを使用してください。
たとえば、次のように定義されたクラスMultiComponent
:
_data class MultiComponent(val x: Int, val y: Int, val z: Int, val a: Int, val b: Int, val c: Int)
_
関数component1()
、component2()
、...、component6()
を含むクラスにコンパイルされ、宣言の構造化解除に使用できます。
_val (q, w, e, r, t, z) = MultiComponent(1, 2, 3, 4, 5, 6)
_
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
必要な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)
そして、必要な建設ヘルパーを生成します。
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)
}
だから私はそれからできる:
val nTuple4 = 1 then 2 then "foo" then "bar"
その結果:
val nTuple4: NTuple4<Int, Int, String, String>
これらのkotlin
クラスをプロジェクトに追加できます。これらのクラスはPair
またはTriple
とまったく同じように機能しますが、より多くのオブジェクトを渡すことができます。
4倍(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)
5つ組(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)