【问题标题】:Why can I not call .values() on generic enum class?为什么我不能在通用枚举类上调用 .values()?
【发布时间】:2019-08-30 18:41:26
【问题描述】:

我知道在枚举类上调用 .values() 会给出枚举案例的数组。但是它不适用于通用枚举类。为什么会这样,我该怎么做才能获得相同的功能?

class EnumEditActivity<E: Enum<E>>() {    
    var value: E? = null
    var allValues: Array<E> = E.values()
}

如果我在普通枚举上调用 values(),它可以正常工作:

enum class Gender {
    male, female
}

for (value in Gender.values()) {
    println(value.name)
}

打印:

male
female

一些答案​​建议这样做:

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

这是行不通的,因为它不是动态的:它总是只会获取 SomeEnum 的情况,因此没有必要使用泛型类。除了 SomeEnum 之外,您不能将任何其他枚举传递给该类,因为一个枚举不能从另一个枚举继承。

我认为这在 Kotlin 中是不可能的。我现在只是定义类,因此它需要您在类初始化程序中传入枚举案例的数组:

class EnumEditActivity<E>(val values: Array<E>)

【问题讨论】:

  • 如果使用纯 Kotlin,这个问题会更有价值,因为您的问题与 Android 无关! :)
  • 谢谢,好点子。已从示例中删除了不必要的 Android 代码
  • 查看我的更新答案。您对Enum 基类的想法已经是正确的方向。请不要将部分答案放在原始问题中,因为它会使其他答案不完整/过时。仅将 cmets 放在特定答案的评论部分中的答案。 :)

标签: generics kotlin enums


【解决方案1】:

因为你必须将函数调用到实例中,而不是类型中,所以你必须具体化类型变量:

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

结果:

A
B
C

【讨论】:

  • .values() 是一个静态函数。例如,您将调用 Gender.values() 并获取一个枚举案例数组。它不适用于实例
  • @mef27 试试 (E::class).values()
  • 我尝试了以下方法,但导致 values() 出现未解决的引用错误
  • inline fun list(): Array { return (E::class).values() }
  • @mef27 给我几分钟我现在正在尝试一些东西
【解决方案2】:

Enum 是所有枚举类的公共基类。您可以使用Enum&lt;*&gt; 作为泛型类型T 的上限。类型必须被重新定义(因此函数inline)因为你需要访问它。

inline fun <reified T: Enum<T>> enumValues(): Array<T> {
    // do something...
    return T::class.java.enumConstants
}

给定一个枚举:

enum class SomeEnum { One, Two }

函数可以这样调用:

println(enumValues<SomeEnum>().toList())

并会返回:

[一,二]

【讨论】:

  • 这个类的重点是它将接受任何枚举并显示可能情况的列表。我不能从 SomeEnum 继承我的枚举(枚举类不能从类继承)所以我不能使用这个函数。
  • 你似乎只是在重新发明enumValues
  • @Slaw 是的,它具有相同的签名,但 OP 要求提供这样的功能,以便他可以添加自定义功能。我编辑了我的答案,试图让它更清楚。我不知道有这样的功能:D。谢谢
【解决方案3】:

您只能通过将类作为参数传递来做到这一点(因为E 是类类型参数,而reified 不可用):

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

或者和你的

class EnumEditActivity<E>(val values: Array<E>)

你可以使用标准的enumValues函数:

inline fun <reified E: Enum<E>> EnumEditActivity() = EnumEditActivity(enumValues<E>())

【讨论】:

    【解决方案4】:

    如果没有编译时安全,您可以使用 Java 的 value.declaringClass.enumConstants

    【讨论】:

    • 值在初始化类时为空,并且仅在用户按下按钮时分配。所以我实际上不能在这里使用 .declaringClass
    猜你喜欢
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    相关资源
    最近更新 更多