Kotlin / Java usam enum em uma instrução switch do tipo Int

Oct 02 2020

Para um projeto Android, tenho um arquivo .kt:

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

E um arquivo .java, onde ocorre o problema:

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;
    }
}

No .Iddá um erro 'Id tem acesso privado em foo.animal', então isso não funciona.

Mudar .Idpara .getId()fornece 'Expressão constante necessária' devido à instrução switch.

É um requisito fora do meu controle que o tipo esteja em intvez da animalassinatura public void processAnimal(int animalId) {e essa seria a solução correta se não estivesse fora do meu controle.

Marcar campos como públicos no arquivo .kt não muda nada.

Existe uma maneira de alcançar o que estou planejando fazer?

Obrigado!

Respostas

4 Alex.T Oct 02 2020 at 14:18

A única maneira que consigo pensar em fazer isso funcionar (devido às limitações do switch java) é criar uma função auxiliar na própria classe enum que nos permitirá traduzir isso Idem um enum Value.

A função java seria:

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;
    }
}

E a classe enum seria mais ou menos assim:

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
        }
    }
}}

Outra maneira de escrever essa função fromInt () seria:

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
}

A segunda opção não é tão legível, mas melhor se tivermos muitos valores enum