Kotlin:如何使用扩展函数扩展枚举类

时间:2016-03-13 04:24:46

标签: enums kotlin kotlin-extension

我正在尝试使用以下函数扩展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 个答案:

答案 0 :(得分:13)

我建议遵循以下解决方案:

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

答案 1 :(得分:4)

我会用通配符稍微改写你的联接:

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())

答案 2 :(得分:3)

@IRus'答案是正确的,但您不必使用反射。对于每个枚举类,编译器会自动生成fixed: 13, (13 unique ids exist) hope: 45, (45 unique ids exist) good: 110, (110 unique ids exist) todo: 414 (414 unique ids exist) 方法。此方法返回包含所有条目的数组。我们可以使扩展函数直接在这个数组上运行,如下所示:

values()

并称之为:

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

答案 3 :(得分:0)

使用::class是一种讨厌的解决方法。 我建议您从stdlib查看enumValues<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>()