Kotlin: как расширить класс enum с помощью функции расширения

Я пытаюсь расширить классы перечислений типа 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);

что я делаю неправильно здесь?

3 ответов


Я предлагаю следующее решение:

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

вместо того, чтобы присоединять функцию расширения к классу, я прикрепил ее к KotlinClass.

теперь вы можете просто использовать это:

enum class Test {ONE, TWO, THREE }

fun main(args: Array<String>) {
    println(Test::class.join())
}
// ONE, TWO, THREE

я перепишу ваше соединение немного так с подстановочным знаком:

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"

поскольку вы определяете join on Class, вам нужен фактический объект класса для его вызова. Классы перечислений, по-видимому, не работают так, но его определенные перечисления могут дать класс с javaClass. Так что это лучшее, что я могу сделать. я думаю, это соответствует общему духу вашей просьбы. Я не знаю, есть ли более элегантный способ достичь того, что вы пытаетесь сделать для всех классов перечисления, подобных этому.

EDIT: вы можете затянуть это немного больше с этим:

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

который позволяет вам звонить так:

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

@IRus' ответ правильный, но вам не нужно использовать отражение. Для каждого класса перечисления a 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()
}