将通用枚举从Java转换为Kotlin

时间:2018-04-02 13:42:03

标签: java generics enums kotlin

我目前正在尝试将一个小型应用程序从java转换为kotlin,而不必重写所有内容,但是我遇到了泛型枚举的问题,因为kotlin并不支持枚举中的泛型。

我在java中有以下枚举:

public enum Property {
    LAST_VIEW(0, 1, Integer.class),
    MAXIMIZED(2, false, Boolean.class),

    private final int       id;
    private final String    defaultValue;
    private final Class<?>  datatype;

    <T> Property(final int id, final T defaultValue, final Class<T> datatype) {
        this.id = id;
        this.defaultValue = defaultValue == null ? null : defaultValue.toString();
        this.datatype = datatype;
    }
}

我将它用于通用属性api,以验证我的默认值是否具有正确的类型,并进行一些运行时检查,以便在我犯错误时立即给出正确的反馈。

有没有在kotlin上做这样的课程,还是我应该考虑重构我的属性api?

2 个答案:

答案 0 :(得分:3)

也许您可以为此考虑密封课程,而不是枚举?

sealed class Property<T>(val id: Int, val defaultValue: T, dataType: Class<T>) 
object LastView : Property<Int>(0, 1, Int::class.java)
object Maximised : Property<Boolean>(2, false, Boolean::class.java)

在这种情况下,由于LastViewMaximized没有任何用户定义或可变状态,我将其定义为objects。由于Property<T>已被密封,因此无法创建其他实例。

答案 1 :(得分:0)

虽然Kotlin不允许构造函数拥有自己的类型参数,但Java中的此功能仅影响调用站点上构造函数参数的类型检查(枚举条目不保留类型安全性)。因此,通过声明一个辅助类泛型类并在辅助构造函数中接受它的实例,可以在Kotlin中实现类似的行为:

class TypedDefaultValue<T>(
    val defaultValue: T,
    val datatype: Class<T>
)

enum class Property(
    val id: Int, 
    val defaultValue: Any, 
    val datatype: Class<out Any>
) {
    LAST_VIEW(0, TypedDefaultValue(1, Int::class.java)), // calls the constructor below
    MAXIMIZED(2, TypedDefaultValue(false, Boolean::class.java));

    constructor(id: Int, typedDefaultValue: TypedDefaultValue<out Any>) :
        this(id, typedDefaultValue.defaultValue, typedDefaultValue.datatype)
}

使用枚举代码中的Any?out Any?来接受可以为空的值。