【问题标题】:Kotlin: Generic Iterator over Enum: how to declare type variablesKotlin:枚举上的通用迭代器:如何声明类型变量
【发布时间】:2018-04-16 10:38:58
【问题描述】:

我的(非编译)枚举通用迭代器代码如下:

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++]
}

IntelliJ IDE 将两个 enumValues 中的 T 标记为红色:

“不能使用 'T' 作为具体类型参数。改用类。”

如何声明类型参数以摆脱错误?

【问题讨论】:

  • 确认一下,你想得到一个Iterator,其中T是一个枚举类型,它的值被迭代了?

标签: generics enums kotlin


【解决方案1】:

没有具体化类型

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

这通过使用函数而不是包装类来工作,根据您的使用,它可能是一个更好的选择。

具有具体化类型

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

这需要明确设置类型,但不需要引用 values 方法。

【讨论】:

  • 不妨简化为fun &lt;T&gt; iterator(values: Array&lt;T&gt;):Iterator&lt;T&gt;iterator(Example.values())
  • enumValues&lt;T&gt;().iterator() 而不是 T::class.java.enumConstants.iterator()?
【解决方案2】:

您需要将类显式传递给构造函数(并且可以在调用站点使用工厂函数来避免它):

class EnumIterator<T: Enum<T>>(clazz: Class<T>): Iterator<T> {
   private var cursor = 0
   // your original code gets them on each hasNext/next call
   private val values = clazz.enumConstants

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

// factory function 
inline fun <reified T: Enum<T>> EnumIterator(): EnumIterator<T> = EnumIterator(T::class.java)

如果您不需要将EnumIterator 作为单独的类型,您也可以稍微简化这一点,方法是将其设为本地(编辑:@jrtapsell 的“使用具体类型”解决方案更好):

inline fun <reified T: Enum<T>> EnumIterator(): Iterator<T> = object : Iterator<T> {
    private var cursor = 0
    private val values = enumValues<T>()

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

【讨论】:

    【解决方案3】:

    enumValues 是一个内联函数,因此必须在编译时知道其具体参数的确切类型,这在您的情况下是不可能的。

    如果您需要迭代器,为什么不直接使用 AnyEnumClass.values().iterator()

    【讨论】:

    • 这个确切的代码是不可能的,问题是如何使它成为可能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多