Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin extension for next Enum value without reflection

Tags:

enums

kotlin

I wrote a Kotlin extension which adds next() for enum values. But is there an better way to do that?

fun <T : Enum<*>> T.next(): T {
    val values = this::class.java.getEnumConstants()
    return if (this.ordinal < values.size - 1) 
            values[this.ordinal + 1] 
        else 
            values[0]
}
enum class Color {Red, Yellow, Green}
Color.Red.next() //Yellow
  1. Can I achieve that without reflections?
  2. If not, how to do that with Kotlins reflection?

The Idea is to iterate from enum value to the next. But only for a specific value, not for whole enum values() list. The thing I want to prevent is to add the following to every enum type:

fun next() = if (this.ordinal == Color.values().size - 1) 
        Color.values()[0] 
    else 
        Color.values()[this.ordinal + 1]
like image 578
Tobse Avatar asked Feb 17 '17 22:02

Tobse


People also ask

Can enum extend another enum Kotlin?

The simple answer is that you can't extend enums in Kotlin the way you would want to.

How do I get the enum value in Kotlin?

You can get the values in an enum using values() , which returns an Array<Types> in this case. You can use firstOrNull as a safe approach, or first if you prefer an exception over null. So add a companion object (which are static relative to the enum, so you can call Types. getByValue(1234) ( Types.

What does enum valueOf return?

valueOf. Returns the enum constant of the specified enum type with the specified name. The name must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)

How to list enum constants in Kotlin?

Enum classes in Kotlin have synthetic methods for listing the defined enum constants and getting an enum constant by its name. The signatures of these methods are as follows (assuming the name of the enum class is EnumClass): EnumClass.valueOf(value: String): EnumClass EnumClass.values(): Array<EnumClass>

How to add extension function to a class in Kotlin?

When a function is added to an existing class it is known as Extension Function. To add an extension function to a class, define a new function appended to the classname as shown in the following example: package kotlin1.com.programmingKotlin.chapter1 class Circle (val radius: Double) {

Is it possible to extend enum without using reflection?

@IRus' answer is correct but you don't have to use reflection. For every enum class, a values () method is automatically generated by the compiler. This method returns an array containing all the entries. We can make the extension function operate directly on this array like this:

What is Kotlin/JS reflection?

Kotlin makes functions and properties first-class citizens in the language, and introspecting them (for example, learning a name or a type of a property or function at runtime) is closely intertwined with simply using a functional or reactive style. Kotlin/JS provides the limited support for reflection features.


1 Answers

You can do that without reflection in Kotlin 1.1 (currently, you can try the 1.1 RC build) using the enumValues<T>(), which does not use the reflection inside, because it is inlined at call sites instead, and the corresponding enum type is placed in the resulting code at compile-time. Example:

inline fun <reified T: Enum<T>> T.next(): T {
    val values = enumValues<T>()
    val nextOrdinal = (ordinal + 1) % values.size
    return values[nextOrdinal]
}

(demo of this code) | The inline and reified are required because enumValues<T>() has reified T.

An alternative that works with Kotlin 1.0.6 (but still uses getDeclaringClass() from Java reflection):

fun <T: Enum<T>> T.next(): T {
    val values = declaringClass.enumConstants
    val nextOrdinal = (ordinal + 1) % values.size
    return values[nextOrdinal]
}
like image 96
hotkey Avatar answered Nov 26 '22 01:11

hotkey