Kotlin: How to extend an enumeration class with an extension function

I am trying to extend the enum classes of type String with the following function, but cannot use it on the call site like this:

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

What am I doing wrong here?

+6
source share
3 answers

I suggest the following solution:

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

Instead of attaching an extension function to a class, I bound it to a KotlinClass.

Now you can just use it:

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

I rewrite your connection a bit like this with a template:

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

Then, if your MyStringEnum is defined as follows:

 enum class MyStringEnum { FOO, BAR, BAZ } 

You can call it like this:

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

to get the exit "FOO, BAR, BAZ"

Since you are defining a union in a class, you need the actual class object to call it. Enum classes do not seem to work this way, but its specific enumerations can produce a class with javaClass . So this is the best I could come up with, and I think it fits the general spirit of your request. I don’t know if there is a more elegant way to achieve what you are trying to do for all enumeration classes like this.

EDIT: You can pull this up a bit:

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

What you can call so:

 println(MyStringEnum.values()[0].join()) 
+3
source
Answer to

@IRus is correct, but you do not need to use reflection. For each enumeration class, the values() method is automatically generated by the compiler. This method returns an array containing all the records. We can make the extension function work directly on this array as follows:

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

And name it as follows:

 fun main(args: Array<String>) { Test.values().join() } 
+3
source

All Articles