Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Generic Iterator over Enum: how to declare type variables

My (non compiling) code for a generic iterator over enumerations is as follows:

class EnumIterator<T: Enum<T>>: Iterator<T> 
{
   private var cursor = 0

   override fun hasNext(): Boolean = cursor < enumValues<T>().size - 1
   override fun next(): T = enumValues<T>()[cursor++]
}

The IntelliJ IDE marks the T in both enumValues< T > red:

"Cannot use 'T' as reified type parameter. Use a class instead."

How to declare the type parameters to get rid of the error?

like image 923
Min-Soo Pipefeet Avatar asked Apr 16 '18 10:04

Min-Soo Pipefeet


People also ask

Can enums have methods Kotlin?

Since Kotlin enums are classes, they can have their own properties, methods, and implement interfaces.

How do I use generic Kotlin?

If a generic type has several type parameters, each of them can be projected independently. For example, if the type is declared as interface Function<in T, out U> you could use the following star-projections: Function<*, String> means Function<in Nothing, String> . Function<Int, *> means Function<Int, out Any?> .


1 Answers

Without reified type

enum class Example {
    A, B, C, D
}

fun <T: Enum<T>> iterator(values:()->Array<T>):Iterator<T> = values()
    .asIterable()
    .iterator()

fun main(args: Array<String>) {

    val iterator = iterator(Example::values)

    iterator.forEach {
        println(it)
    }
}

This works by using a function instead of a wrapper class, depending on your use it may be a better option.

With reified type

enum class Example {
    A, B, C, D
}

inline fun <reified T: Enum<T>> iterator():Iterator<T> = enumValues<T>().iterator()

fun main(args: Array<String>) {

    val iterator = iterator<Example>()

    iterator.forEach {
        println(it)
    }
}

This requires the type to be explicitly set, but does not need a reference to the values method.

like image 167
jrtapsell Avatar answered Nov 11 '22 03:11

jrtapsell