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
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]
The simple answer is that you can't extend enums in Kotlin the way you would want to.
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.
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.)
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>
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) {
@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:
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.
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]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With