关于解构表达式的扩展使用


#1

【问题来由】:使用解构表达式定义变量十分方便,一行表达式可以定义多个变量,但是定义4个以上的变量需要自己实现。

val (a, b) = 1 to 2
val (c, d, e) = Triple(3, 4, 5)

四个以上时需自己定义data class 或者重写componentN方法

data class MyData<out A, out B, out C, out D>(val a: A, val b: B, val c: C, val d: D)

class MyData2<A, B, C, D>(var a: A, var b: B, var c: C, var d: D) {
    operator fun component1() = a
    operator fun component2() = b
    operator fun component3() = c
    operator fun component4() = d
}

4个及以上都要自定义这种类,能否实现一个类,支持n个变量使用解构表达式同时初始化呢?类似以下

val (a, b, c) = 1 and 2 and 3

#2

写个脚本直接生成 Tuple2, Tuple3, Tuple4 … Tuple999 这些类

Ktorm 就是这样做的: https://github.com/vincentlauvlwj/Ktorm/blob/master/ktorm-core/generate-tuples.gradle#L5


#3

and 方法也可以直接生成,比如 Tuple2 的 and 方法返回值为 Tuple3,Tuple3 的 and 方法返回值为 Tuple4

把这些生成的代码打成一个 jar 包,然后别的地方用起来就很方便了


#4

作用是动态生成一个 Tuples.kt 文件?这个文件在编译的时候生成吗,具体啥作用呢


#5

这东西超过10个我就觉得需求不合理了。不过我还是写了个这个

跟楼上的做法类似


#6

添加依赖,20个以内的元素都可以通过

1 U 2 U 3 "hello"

这样的形式创建tuple,当然也可以用 tupleOf


#7

对的,就是生成一个 Tuples.kt,里面的内容挺无聊的,手写估计会想死,所以才用脚本生成

大概是这样(当然不止这几个):

/**
 * Set a typealias `Tuple2` for `Pair`. 
 */
typealias Tuple2<E1, E2> = Pair<E1, E2>

/**
 * Set a typealias `Tuple3` for `Triple`.
 */
typealias Tuple3<E1, E2, E3> = Triple<E1, E2, E3>

/** 
 * Represents a tuple of 4 values.
 *
 * There is no meaning attached to values in this class, it can be used for any purpose.
 * Two tuples are equal if all the components are equal.
 */
data class Tuple4<out E1, out E2, out E3, out E4>(
    val element1: E1,
    val element2: E2,
    val element3: E3,
    val element4: E4
) : Serializable { 

    override fun toString(): String { 
        return "($element1, $element2, $element3, $element4)"
    }
}

/** 
 * Represents a tuple of 5 values.
 *
 * There is no meaning attached to values in this class, it can be used for any purpose.
 * Two tuples are equal if all the components are equal.
 */
data class Tuple5<out E1, out E2, out E3, out E4, out E5>(
    val element1: E1,
    val element2: E2,
    val element3: E3,
    val element4: E4,
    val element5: E5
) : Serializable { 

    override fun toString(): String { 
        return "($element1, $element2, $element3, $element4, $element5)"
    }
}

#8

优秀 :+1:


#9

不用自定义了啊。List 就可以实现:

val list = listOf(1,2,3,4,…)

val (a,b,c,d,e) = list


#10

优秀哦,感谢提醒


#11

如果是不同类型的呢

val (a, b) = listOf(1, "2")

你以为这样子 a 的类型就是 Int,b 的类型就是 String 吗,然而它们都是 Any。。。


#12

是的,而且listOf,arrayOf这些只支持5个以内的参数初始化,并且类型不同会被转成Any


#13

image


京ICP备16022265号-2 Kotlin China 2017 - 2018