【问题标题】:How to access Enum property and functions in Kotlin如何在 Kotlin 中访问 Enum 属性和函数
【发布时间】:2019-02-11 06:52:00
【问题描述】:

以下枚举定义有效。是否可以访问“内部属性”auditData 或函数audit?

enum class GWGStatus {
    UNCHECKED,
    CHECKED {
        lateinit var auditDate: Date
        fun auditor() : String = "Peter"
    }
}

GWGStatus.CHECKED.??? (does not work)

【问题讨论】:

标签: enums kotlin


【解决方案1】:

您必须在 enum 类型本身中声明变量和函数,然后在 enum 实例中覆盖它们。

不幸的是,由于并非所有 enum 实例都实现了该功能,因此您无法使其成为 abstract 并且必须提供默认实现:

import java.util.*

enum class GWGStatus {
    UNCHECKED,
    CHECKED {
        override lateinit var auditDate: Date
        override fun auditor(): String = "Peter"
    };

    open lateinit var auditDate: Date
    open fun auditor(): String = ""
}

fun main(vararg args: String) {
    GWGStatus.CHECKED.auditDate = Date()

    println(GWGStatus.CHECKED.auditDate)
    println(GWGStatus.CHECKED.auditor())
}

但是请注意,enum 的用法感觉很奇怪。您将状态数据存储在旨在成为常量对象的东西中。内存中只会有一个 GWGStatus.CHECKED 对象,因此它似乎不是存储状态信息的正确位置。

【讨论】:

    【解决方案2】:

    我一看到这个,就需要查找字节码,因为我无法想象它应该被翻译成什么。虽然我认为“它”是一个错误,但我将向您展示我目前发现的内容。

    对于CHECKED,实际上创建了自己的子类,即public final class GWGStatus$CHECKED extends GWGStatus,尽管GWGStatus 本身就是一个枚举。可能又是 JVM 字节码中允许但在 Java 语言规范中不允许的东西。

    现在是不太一致的部分。虽然以下在 Java 中有效:

    GWGStatus.CHECKED status = (GWGStatus.CHECKED) GWGStatus.CHECKED;
    status.auditDate = new Date();
    System.out.println(status.auditor());
    

    并按预期打印 Peter,在 Kotlin 中无法进行转换(还没有?):

    GWGStatus.CHECKED as GWGStatus.CHECKED // fails: Use of enum entry names as types is not allowed, use enum type instead
    

    现在在 Kotlin 中使用 Java 反射实用程序(例如 status::class.java.declaredFields.java.declaredMethodsauditor()getAuditDate()(等)都是可见且可访问的(正如 Java 代码本身已经证明的那样)。进一步分析,只使用 Kotlin 反射:

    GWGStatus.UNCHECKED::class // returns class GWGStatus
    GWGStatus.CHECKED::class // return class GWGStatus$CHECKED ... that's good so far
    GWGStatus.CHECKED::class.declaredMembers // empty list ... didn't expect this one
    // empty too: GWGStatus.CHECKED::class.declaredMemberProperties
    // and GWGStatus.CHECKED::class.declaredFunctions
    GWGStatus.CHECKED::class.superTypes // shows GWGStatus as expected
    GWGStatus.CHECKED::class.members // shows clone(), finalize(), name, equals, hashcode, tostring, getdeclaringclass, ordinal... nothing we are interested in and rather the ~general enum members
    GWGStatus::class.nestedClasses // empty too
    

    好的...我们无法使用 Kotlin 反射看到它们(或者我可能没有使用正确的方法?;-))。所以:这里有些东西闻起来像一个错误,但我还不确定这个错误是什么:

    1. 难道一开始就不应该创建子类吗?
    2. 子类是否应该在 Kotlin 本身中可访问和可见?
    3. Kotlin 编译器是否应该抱怨这一点,因为这还没有完成?
    4. 实际上是错误消息错误,它应该只是允许演员?
    5. 还有别的吗?

    【讨论】:

    • but isn't allowed in the Java language specification. - 正如您自己的示例一样,它在 Java 中工作的事实表明它在 Java 语言规范中。
    • 仅仅因为某些东西有效,并不一定意味着它是这样指定的...如果您在 java 语言规范中找到相关内容,请分享指向它的链接...
    【解决方案3】:

    你也可以只使用构造函数:

    enum class GWSGStatus(var date: Date, private var auditor: String) {
        UNCHECKED(Date(), ""),
        CHECKED(Date(), "Peter");
    
        fun auditor() = auditor
    }
    

    这仍然取决于这个枚举的用法。 关注之前的帖子

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-18
      • 2015-09-02
      • 1970-01-01
      • 2017-03-04
      • 1970-01-01
      • 2020-11-21
      • 2012-07-27
      • 1970-01-01
      相关资源
      最近更新 更多