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