14

我正在尝试String使用以下函数扩展枚举类型的类,但无法在调用站点使用它,如下所示:

fun <T: Enum<String>> Class<T>.join(skipFirst: Int = 0, skipLast: Int = 0): String {
    return this.enumConstants
        .drop(skipFirst)
        .dropLast(skipLast)
        .map { e -> e.name }
        .joinToString()
}

MyStringEnum.join(1, 1);

我在这里做错了什么?

4

4 回答 4

16

我建议以下解决方案:

fun <T : Enum<*>> KClass<T>.join(skipFirst: Int = 0, skipLast: Int = 0): String {
    return this.java
            .enumConstants
            .drop(skipFirst)
            .dropLast(skipLast)
            .map { e -> e.name }
            .joinToString()
}

我没有将扩展函数附加到 Class,而是将其附加到 KotlinClass。

现在,您可以简单地使用它:

enum class Test {ONE, TWO, THREE }

fun main(args: Array<String>) {
    println(Test::class.join())
}
// ONE, TWO, THREE
于 2016-03-13T05:40:13.213 回答
7

@IRus 的回答是正确的,但您不必使用反射。对于每个枚举类,values()编译器会自动生成一个方法。此方法返回一个包含所有条目的数组。我们可以让扩展函数直接对这个数组进行操作,如下所示:

fun <T : Enum<*>> Array<T>.join(skipFirst: Int = 0, skipLast: Int = 0)
        = drop(skipFirst)
        .dropLast(skipLast)
        .map { e -> e.name }
        .joinToString()

并这样称呼它:

fun main(args: Array<String>) {
    Test.values().join()
}
于 2016-03-15T16:10:09.500 回答
7

使用::class是一个讨厌的解决方法。我建议您查看stdlibenumValues<E>enumValueOf<E>以相同的方式进行操作:

inline fun <reified E : Enum<E>> joinValuesOf(skipFirst: Int = 0, skipLast: Int = 0): String =
        enumValues<E>().join(skipFirst, skipLast)

@PublishedApi
internal fun Array<out Enum<*>>.join(skipFirst: Int, skipLast: Int): String =
        asList()
                .subList(skipFirst, size - skipLast)
                .joinToString(transform = Enum<*>::name)

用法:joinValuesOf<Thread.State>()

于 2019-10-30T13:14:44.953 回答
5

我会用通配符稍微改写你的加入:

fun <T: Enum<*>> Class<T>.join(skipFirst: Int = 0, skipLast: Int = 0): String {
    return this.enumConstants
            .drop(skipFirst)
            .dropLast(skipLast)
            .map { e -> e.name }
            .joinToString()
}

然后,假设您的 MyStringEnum 定义如下:

enum class MyStringEnum { FOO, BAR, BAZ }

你可以这样称呼它:

println(MyStringEnum.values()[0].javaClass.join())

获得输出“FOO,BAR,BAZ”

由于您在 Class 上定义连接,因此您需要一个实际的 Class 对象来调用它。枚举类显然不能那样工作,但它定义的枚举可以产生一个带有javaClass. 所以这是我能想到的最好的,我认为符合您要求的一般精神。我不知道是否有更优雅的方式来实现你想要为所有这样的枚举类做的事情。

编辑:你可以用这个把它收紧一点:

fun Enum<*>.join(skipFirst: Int = 0, skipLast: Int = 0): String {
    return this.javaClass.join(skipFirst, skipLast)
}

这让您可以这样调用:

println(MyStringEnum.values()[0].join())
于 2016-03-13T05:18:39.503 回答