Kotlin / Java используют enum в операторе switch типа Int

Oct 02 2020

Для проекта Android у меня есть файл .kt:

class foo () {
    enum class animal (var Id: Int) {
        CAT(0),
        DOG(1),
        FISH(2),
    }
}

И файл .java, в котором возникает проблема:

public void processAnimal(int animalId) {
    switch(animalId) {
        case foo.animal.CAT.Id:
            //do something
            break;
        case foo.animal.DOG.Id:
            //do something else
            break;
        case foo.animal.FISH.Id:
            //do something fishy
            break;
    }
}

На .Idэкране появляется сообщение об ошибке «У Id есть частный доступ к foo.animal», поэтому это не работает.

Изменение .Idна .getId()дает «Требуется постоянное выражение» из-за оператора switch.

Это не зависящее от меня требование, чтобы тип был intвместо animalподписи, public void processAnimal(int animalId) {и это было бы правильным решением, если бы оно не было вне моего контроля.

Отметка полей как общедоступных в файле .kt ничего не меняет.

Есть ли способ достичь того, что я собираюсь делать?

Спасибо!

Ответы

4 Alex.T Oct 02 2020 at 14:18

Единственный способ, которым я могу представить эту работу (из-за ограничений переключателя java), - это создать вспомогательную функцию в самом классе перечисления, которая позволит нам преобразовать ее Idв перечисление Value.

Функция java будет такой:

public void processAnimal(int animalId) {
    AnimalEnum animalEnum = AnimalEnum.fromInt(animalId);
    switch(animalEnum) {
        case CAT:
            //do something
            break;
        case DOG:
            //do something else
            break;
        case FISH:
            //do something fishy
            break;
    }
}

И класс enum будет выглядеть примерно так:

enum class AnimalEnum(val Id: Int) { //classes should start with an uppercase letter in kotlin
CAT(0),
DOG(1),
FISH(2);

companion object {
    @JvmStatic //to be accessible from java
    fun fromInt(givenInt: Int): AnimalEnum {
        return when (givenInt) {
            CAT.Id -> CAT
            DOG.Id -> DOG
            FISH.Id -> FISH
            else -> throw Exception("Invalid id `$givenInt`, available ids are ${values().map { it.Id }}") // or a null or something
        }
    }
}}

Другой способ написать эту функцию fromInt ():

companion object {
    private val map = values().associateBy(AnimalEnum::Id)
    @JvmStatic //to be accessible from java
    fun fromInt(givenInt: Int) = map[givenInt] ?: throw Exception("Invalid id `$givenInt`, available ids are ${values().map { it.Id }}") // or a null or something
}

Второй вариант не так удобен для чтения, но лучше, если у нас много значений перечисления