Как мне создать enum из Int в Kotlin? - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть enum:

enum class Types(val value: Int) {
    FOO(1)
    BAR(2)
    FOO_BAR(3)
}

Как мне создать экземпляр этого enum, используя Int?

Я попытался сделать что-то вроде этого:

val type = Types.valueOf(1)

И я получаю ошибку:

Целочисленный литерал не соответствует ожидаемому типу String

Ответы [ 5 ]

0 голосов
/ 28 ноября 2018

Я бы построил «обратную» карту раньше времени.Вероятно, не большое улучшение, но и не так много кода.

enum class Test(val value: Int) {
    A(1),
    B(2);

    companion object {
        val reverseValues: Map<Int, Test> = values().associate { it.value to it }
        fun valueFrom(i: Int): Test = reverseValues[i]!!
    }
}

Редактировать: map ... toMap() изменено на associate за предложение @ горячей клавиши.

0 голосов
/ 28 ноября 2018

Это действительно зависит от того, что вы на самом деле хотите сделать.

  • Если вам нужно конкретное жестко закодированное значение перечисления, то вы можете напрямую использовать Types.FOO
  • Если вы получаетезначение динамически откуда-то еще в вашем коде, вы должны попытаться использовать тип enum напрямую, чтобы не выполнять такого рода преобразования
  • Если вы получаете значение из веб-службы, должно быть что-тов вашем инструменте десериализации, чтобы разрешить этот тип преобразования (например, @JsonValue) Джексона
  • Если вы хотите получить значение enum на основе одного из его свойств (например, свойства value здесь), то я 'Боюсь, вам придется реализовать свой собственный метод преобразования, как указывал @Zoe.

Один из способов реализации этого пользовательского преобразования - добавление объекта-компаньона с методом преобразования:

enum class Types(val value: Int) {
    FOO(1),
    BAR(2),
    FOO_BAR(3);

    companion object {
        private val types = values().associate { it.value to it }

        fun findByValue(value: Int) = types[value]
    }
}

Объекты-компаньоны в Kotlin должны содержать члены, которые принадлежат к классу, но не привязаны ни к какому экземпляру (например, Java static).члены).Реализация метода позволяет вам получить доступ к вашему значению, вызвав:

var bar = Types.findByValue(2)
0 голосов
/ 28 ноября 2018

Наивным способом может быть:

enum class Types(val value: Int) {
    FOO(1),
    BAR(2),
    FOO_BAR(3);

    companion object {
        fun valueOf(value: Int) = Types.values().find { it.value == value }
    }
}

Тогда вы можете использовать

var bar = Types.valueOf(2)
0 голосов
/ 28 ноября 2018

Enum#valueOf основано на имени .Что означает, чтобы использовать это, вам нужно будет использовать valueof("FOO").Метод valueof также принимает строку, которая объясняет ошибку.Строка не Int;типы имеют значение.Причина, по которой я упомянул, что она делает, в том, что вы знаете, что это не тот метод, который вы ищете

Если вы хотите получить его на основе значения типа int, вам нужно определить собственную функцию для этого.Вы можете получить значения в перечислении, используя values(), что в этом случае возвращает Array<Types>.Вы можете использовать firstOrNull в качестве безопасного подхода или first, если вы предпочитаете исключение, а не ноль.

Поэтому добавьте объект-компаньон (который является статическим относительно перечисления, чтобы вы могли вызывать Types.getByValue(1234) (Types.COMPANION.getByValue(1234) из Java) через Types.FOO.getByValue(1234).

companion object {
    private val values = values();
    fun getByValue(value: Int) = values.firstOrNull { it.value == value }
}

values() возвращает новый массив каждый раз, когда он вызывается, что означает, что вы должны кэшировать его локально, чтобы не создавать заново каждый раз, когда вы вызываете getByValue. Если вы вызываете values() при вызове метода, вы рискуете воссоздать егонесколько раз (в зависимости от того, сколько раз вы на самом деле вызываете его), что является пустой тратой памяти.

Функция также может быть расширена и проверять на основе нескольких параметров, если это то, что вы хотите сделать. Эти типыфункций не ограничены одним аргументом.

Именование функции полностью зависит от вас. Это не обязательно должно быть getByValue.

0 голосов
/ 28 ноября 2018
enum class Types(val value: Int) {
    FOO(1),
    BAR(2),
    FOO_BAR(3);

    companion object {
        fun fromInt(value: Int) = Types.values().first { it.value == value }
    }
}

Вы можете добавить проверку безопасности для диапазона и вернуть ноль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...