【问题标题】:Kotlin: access companion data in generic functionKotlin:在通用函数中访问伴随数据
【发布时间】:2020-12-04 01:02:28
【问题描述】:

我在 Kotlin 中有一个列出枚举值的简单任务:

interface DisplayableEnum<E: Enum<E>> {
    val displayValue: String
}

inline fun <reified T> printAllValues(selected: T?) where T: Enum<T>, T: DisplayableEnum<T> {
    println("All Values:")
    enumValues<T>().forEach {
        println(it.displayValue)
    }
    selected?.let { println("\nSelected: ${it.displayValue}") }
}


////// USAGE

enum class MyEnum(override val displayValue: String): DisplayableEnum<MyEnum> {
    A("value is A"),
    B("value is B")
}

fun main() {
    // with a selected value
    f(MyEnum.A)

    // without a selected value
    f(null as MyEnum?)
}

现在假设我传递给printAllValues 的所有枚举也应该有一个名为defaultValue 的字段。如果是MyEnum,我会这样写:

enum class MyEnum(override val displayValue: String): DisplayableEnum<MyEnum> {
    A("value is A"),
    B("value is B");

    companion object {
        val defaultValue = A
    }
}

所以我的问题是:有没有办法在 Kotlin 中定义这样的合同?

理想情况下,我想以某种方式在接口中定义该合约,例如上面的DisplayableEnum,然后以某种方式在printAllValues 中使用它,如下所示:

inline fun <reified T> printAllValues(selected: T) where T: Enum<T>, T: DisplayableEnum<T> {
    println("All Values:")
    enumValues<T>().forEach {
        println(it.displayValue)
    }
    selected?.let { println("\nSelected: ${it.displayValue}") }
    println("Default value: ${T.defaultValue???}"
}

我不想要的一件事是使用非伴随 defaultValue,我总是必须手动将它传递给函数(但是为什么如果类型包含所有信息?)或者,如果非同伴:

interface DisplayableEnum<E: Enum<E>> {
    val displayValue: String
    val defaultValue: E
}

然后通过一个对象访问它——做一些丑陋的事情,比如enumValues&lt;T&gt;().first().defaultValue

我想知道 Kotlin 是否有针对这种情况的解决方案。

【问题讨论】:

  • 不,同伴是完全不同的对象,你不能通过其他类的实例来引用它们。

标签: kotlin generics enums


【解决方案1】:

不可能在伴生对象中定义抽象属性。 所以应该直接在接口中定义。

这里的棘手部分是在没有编译器警告的情况下实现这个接口:

enum class MyEnum(override val displayValue: String) : DisplayableEnum<MyEnum> {
    A("value is A"),
    B("value is B");

    override val defaultValue: MyEnum by lazy { A }
}

如果你觉得enumValues&lt;T&gt;().first().defaultValue很丑,把它包装到辅助函数中:

inline fun <reified T> enumDefaultValue(): T where T : Enum<T>, T : DisplayableEnum<T> =
    enumValues<T>().first().defaultValue

//Usage:
println("Default value: ${enumDefaultValue<T>()}")

【讨论】:

  • 感谢让我更高效,我用override val defaultValue get() = A代替了lazy,没想到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
  • 1970-01-01
  • 2019-12-31
  • 2019-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多