Effective Enums in Kotlin with reverse lookup?

后端 未结 12 1677
野性不改
野性不改 2020-11-30 01:40

I\'m trying to find the best way to do a \'reverse lookup\' on an enum in Kotlin. One of my takeaways from Effective Java was that you introduce a static map inside the enum

相关标签:
12条回答
  • 2020-11-30 01:52

    True Idiomatic Kotlin Way. Without bloated reflection code:

    interface Identifiable<T : Number> {
    
        val id: T
    }
    
    abstract class GettableById<T, R>(values: Array<R>) where T : Number, R : Enum<R>, R : Identifiable<T> {
    
        private val idToValue: Map<T, R> = values.associateBy { it.id }
    
        operator fun get(id: T): R = getById(id)
    
        fun getById(id: T): R = idToValue.getValue(id)
    }
    
    enum class DataType(override val id: Short): Identifiable<Short> {
    
        INT(1), FLOAT(2), STRING(3);
    
        companion object: GettableById<Short, DataType>(values())
    }
    
    fun main() {
        println(DataType.getById(1))
        // or
        println(DataType[2])
    }
    
    0 讨论(0)
  • 2020-11-30 01:52

    val t = Type.values()[ordinal]

    :)

    0 讨论(0)
  • 2020-11-30 01:58

    Another example implementation. This also sets the default value (here to OPEN) if no the input matches no enum option:

    enum class Status(val status: Int) {
    OPEN(1),
    CLOSED(2);
    
    companion object {
        @JvmStatic
        fun fromInt(status: Int): Status =
            values().find { value -> value.status == status } ?: OPEN
    }
    

    }

    0 讨论(0)
  • 2020-11-30 02:00

    Came up with a more generic solution

    inline fun <reified T : Enum<*>> findEnumConstantFromProperty(predicate: (T) -> Boolean): T? =
    T::class.java.enumConstants?.find(predicate)
    

    Example usage:

    findEnumConstantFromProperty<Type> { it.value == 1 } // Equals Type.A
    
    0 讨论(0)
  • 2020-11-30 02:01

    Another option, that could be considered more "idiomatic", would be the following:

    companion object {
        private val map = Type.values().associateBy(Type::value)
        operator fun get(value: Int) = map[value]
    }
    

    Which can then be used like Type[type].

    0 讨论(0)
  • 2020-11-30 02:10

    First of all, the argument of fromInt() should be an Int, not an Int?. Trying to get a Type using null will obviously lead to null, and a caller shouldn't even try doing that. The Map has also no reason to be mutable. The code can be reduced to:

    companion object {
        private val map = Type.values().associateBy(Type::value)
        fun fromInt(type: Int) = map[type]
    }
    

    That code is so short that, frankly, I'm not sure it's worth trying to find a reusable solution.

    0 讨论(0)
提交回复
热议问题