I know that calling .values() on an enum class gives an array of the enum cases. However it doesn't work with a generic enum class. Why is this, and what can I do to get the same functionality?
class EnumEditActivity<E: Enum<E>>() {
var value: E? = null
var allValues: Array<E> = E.values()
}
If I call values() on a normal enum, it works fine:
enum class Gender {
male, female
}
for (value in Gender.values()) {
println(value.name)
}
prints:
male
female
Some answers suggest doing something like this:
enum class SomeEnum {
one, two
}
class EnumEditActivity<E: SomeEnum>() {
var value: E? = null
val values = listCases<SomeEnum>()
inline fun <reified E: SomeEnum> listCases() = (E::class.java).enumConstants.toList()
}
This doesn't work because it's not dynamic: it will always just get the cases for SomeEnum, so there's no point having a generic class. You can't pass any other enum apart from SomeEnum into the class, because one enum cannot inherit from another.
I don't think this is possible in Kotlin. I'm now just defining the class so it requires you to pass in an array of the enum's cases in the class initializer:
class EnumEditActivity<E>(val values: Array<E>)
However, it is possible to use enums in generics. The MSDN article for Enum gives the following type definition for the class Enum . This definition can be used to get enum s working as generic types by constraining the generic type to those of Enum .
Overview. The Java enum type provides a language-supported way to create and use constant values. By defining a finite set of values, the enum is more type safe than constant literal variables like String or int.
Since C# doesn't support enum with string value, in this blog post, we'll look at alternatives and examples that you can use in code to make your life easier. The most popular string enum alternatives are: Use a public static readonly string. Custom Enumeration Class.
An enum is usually selected specifically because it is immutable - i.e. you would never want the values to change as it would make your application unpredictable.
Because you have to call the function into the instance, not the type, to do so you have to reify the type variable:
interface VisualEnum {
fun get(fromName : String)
}
enum class VisuelEnumSub(lowerName: String) : VisualEnum {
A("a"), B("b"), C("c");
override fun get(name : String) {
VisuelEnumSub.values().filter { it.toString().equals(name, true) }
}}
open class AppCompatActivity{}
open class EnumEditActivity<E: VisualEnum>(): AppCompatActivity() {
inline fun <reified A:E> onCreate() = (A::class.java).enumConstants
}
fun main(args: Array<String>) {
EnumEditActivity<VisuelEnumSub>().onCreate<VisuelEnumSub>().forEach { println(it) }
}
result:
A
B
C
You can only do this by passing the class as a parameter (because E
is a class type parameter and reified
isn't available):
class EnumEditActivity<E: Enum<E>>(cls: Class<E>) {
var value: E? = null
var allValues: Array<E> = cls.enumConstants
}
inline fun <reified E: Enum<E>> EnumEditActivity() = EnumEditActivity(E::class.java)
// call as
EnumEditActivity<YourEnum>()
Or with your
class EnumEditActivity<E>(val values: Array<E>)
you can use the standard enumValues
function:
inline fun <reified E: Enum<E>> EnumEditActivity() = EnumEditActivity(enumValues<E>())
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