Инициализировать перечисление из связанного значения

Я хотел бы инициализировать enum связанным с ним значением.

Мое перечисление:

enum class DirectionSwiped(raw: Int){
    LEFT(4),
    RIGHT(8);
}

Я хотел бы инициализировать его как таковой:

val direction = DirectionSwiped(raw: 4)

Но я получаю такую ​​ошибку:

Enum type cannot be instantiated

Почему это происходит? В Swift эта функция работает так:

enum Direction: Int {
    case right = 2
}

let direction = Direction(rawValue: 2)

Как заставить его работать в Котлине?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
2 237
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как говорится в ошибке, вы не можете создавать экземпляры перечислений в Kotlin. Возможный обходной путь - использовать карту и 2 вспомогательных метода для получения значений перечисления из необработанных значений и наоборот:

enum class DirectionSwiped {
    LEFT,
    RIGHT;

    fun toRaw() = enumToRaw[this]
    companion object {
        val rawToEnum = mapOf(
                4 to LEFT,
                8 to RIGHT
        )
        val enumToRaw = rawToEnum.entries.associate{(k,v)-> v to k}
        fun ofRaw(raw: Int): DirectionSwiped? = rawToEnum[raw]
    }
}

Использование:

val direction = DirectionSwiped.ofRaw(4) // LEFT
val raw = DirectionSwiped.LEFT.toRaw() // 4

Спасибо за ответ, но мне кажется глупым, что на таком современном языке, как Kotlin, мы не можем делать это так, как быстро!

Mickael Belhassen 17.12.2018 21:34

Совершенно небезопасно, DirectionSwiped.ofRaw(5) возвращает null, потенциально вызывая сбои во время выполнения

Omar Mainegra 17.12.2018 23:08

@OmarMainegra возвращает значение типа DirectionSwiped? - обратите внимание на ?. Так что да, конечно, он может вернуть null, что еще он вернет, если совпадения нет? Но благодаря типам Kotlin, допускающим значение NULL, это действительно спасает.

Patric 17.12.2018 23:16

@Tagas И вы планируете сделать это для всех перечислений, которые вы определяете ?? также нет необходимости определять Map, для этого достаточно DirectionSwiped.values().firstOrNull { it.raw == 5 }

Omar Mainegra 17.12.2018 23:19

@OmarMainegra Это зависит от количества перечисляемых значений. Если это всего лишь пара, то, конечно, ваше решение идеально подходит. Однако, если есть много значений и доступов, карта будет намного более производительной.

Patric 17.12.2018 23:20

@Tagas, вам не хватает точки использования перечисления, они должны быть типами копродуктов, то же самое с запечатанным классом, иерархия закрытых типов для получения помощи от компилятора (например, инструкция when), поэтому это опасно, не тогда используйте перечисления

Omar Mainegra 17.12.2018 23:23
Ответ принят как подходящий

Да, ты можешь

enum class DirectionSwiped(val raw: Int){
    LEFT(4),
    RIGHT(8);
}

val left = DirectionSwiped.LEFT
val right = DirectionSwiped.RIGHT

val leftRaw = DirectionSwiped.LEFT.raw
val rightRaw = DirectionSwiped.LEFT.raw

val fromRaw = DirectionSwiped.values().firstOrNull { it.raw == 5 }

Это был бы правильный способ доступа к экземплярам enum class.

Что вы пытаетесь сделать, так это создать новый экземпляр вне сайта определения, что невозможно для классов enum или sealed, поэтому в ошибке говорится, что конструктор частный

Это, очевидно, работает, но вопрос заключался в получении значения enum по необработанному значению, а не в получении необработанного значения, если у вас уже есть значение enum ...

Patric 17.12.2018 23:11

@Tagas Я тоже упоминаю об этом (например, fromRaw), ваш ответ вводит в заблуждение, потому что он может и потерпит неудачу

Omar Mainegra 17.12.2018 23:14

Я не вижу вашей проблемы ... ваш DirectionSwiped.values().firstOrNull { it.raw == 5 } возвращает тот же тип, что и моя функция ofRaw: DirectionSwiped?

Patric 17.12.2018 23:19

@Tagas Но я ясно выражаюсь, используя firstOrNull, с первого взгляда вы видите, что он делает, в вашем случае нет

Omar Mainegra 17.12.2018 23:24

Будет предупреждение компилятора, я не знаю, как вы можете быть более явным, чем это ... В любом случае, давайте не будем добавлять больше бесполезных обсуждений, это никуда не денется.

Patric 17.12.2018 23:27

@Tagas Вы правы, это бессмысленно, кстати, вы не видите предупреждения компилятора, когда читаете код в github, также общедоступные функции, такие как ваш toRaw, должны явно указывать тип возвращаемого значения по той же причине (а вы этого не делаете это, поэтому сейчас сложно, когда ваша функция возвращает значение NULL)

Omar Mainegra 17.12.2018 23:35

Достаточно честно, позвольте мне это исправить :)

Patric 17.12.2018 23:38

Другие вопросы по теме