Intereting Posts
Android Kotlin: java.lang.NoClassDefFoundError: сбой разрешения: <KotlinObject> Kotlin: доступ к параметру when-statement Создайте приложение для Android, написанное в Kotlin, используя систему Buck build В Котлине, почему Джексон в некоторых случаях отказывается от несанкционированного не аннотированного объекта, а не в других Объект базы данных Singleton с параметризованной инициализацией при запуске? Как вызвать конструктор String Java (char , int offset, int length) из Kotlin? Не удалось запустить котлин с кинжалом 2 В Kotlin, как я идиоматически обращаюсь к значениям вложенной карты с нулевым значением или возвращать значение по умолчанию? Преобразование HashMap с помощью moshi Класс данных KotlinReflectionInternalError Использовать группу в ConstraintLayout для прослушивания событий кликов на нескольких представлениях Может ли класс данных Kotlin иметь более одного конструктора? ImageButton OnClickListener не работает Как использовать настраиваемые типы для параметров Retrofit @Query? Сбой сборки при использовании «kotlin-kapt» с Realm

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

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

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

 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»

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

EDIT: вы можете немного подтянуть это:

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

Что вы можете назвать следующим:

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

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