Kotlin:如何使用扩展函数扩展枚举 class
Kotlin: How to extend the enum class with an extension function
我正在尝试使用以下函数扩展 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<*>> 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 对象来调用它。枚举 类 显然不是那样工作的,但它定义的枚举可以产生 Class 和 javaClass
。所以这是我能想到的最好的,我认为符合您要求的一般精神。我不知道是否有更优雅的方法来实现您为所有枚举 类 所做的事情。
编辑:你可以用这个来收紧一点:
fun Enum<*>.join(skipFirst: Int = 0, skipLast: Int = 0): String {
return this.javaClass.join(skipFirst, skipLast)
}
这让你可以这样调用:
println(MyStringEnum.values()[0].join())
我建议采用以下解决方案:
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
@IRus 的回答是正确的,但您不必使用反射。对于每个枚举 class,编译器会自动生成一个 values()
方法。此方法 returns 一个包含所有条目的数组。我们可以像这样让扩展函数直接操作这个数组:
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()
}
使用 ::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>()
我正在尝试使用以下函数扩展 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<*>> 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 对象来调用它。枚举 类 显然不是那样工作的,但它定义的枚举可以产生 Class 和 javaClass
。所以这是我能想到的最好的,我认为符合您要求的一般精神。我不知道是否有更优雅的方法来实现您为所有枚举 类 所做的事情。
编辑:你可以用这个来收紧一点:
fun Enum<*>.join(skipFirst: Int = 0, skipLast: Int = 0): String {
return this.javaClass.join(skipFirst, skipLast)
}
这让你可以这样调用:
println(MyStringEnum.values()[0].join())
我建议采用以下解决方案:
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
@IRus 的回答是正确的,但您不必使用反射。对于每个枚举 class,编译器会自动生成一个 values()
方法。此方法 returns 一个包含所有条目的数组。我们可以像这样让扩展函数直接操作这个数组:
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()
}
使用 ::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>()