Kotlin / Java utilizza enum in un'istruzione switch di tipo Int

Oct 02 2020

Per un progetto Android, ho un file .kt:

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

E un file .java, dove si verifica il 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;
    }
}

Sul .Idviene visualizzato un errore "Id ha accesso privato in foo.animal", quindi non funziona.

La modifica .Idin .getId()restituisce "Espressione costante richiesta" a causa dell'istruzione switch.

È un requisito fuori dal mio controllo che il tipo sia intinvece che animalnella firma public void processAnimal(int animalId) {e questa sarebbe la soluzione corretta se non fosse fuori dal mio controllo.

Contrassegnare i campi come pubblici nel file .kt non cambia nulla.

C'è un modo per ottenere ciò che mi propongo di fare?

Grazie!

Risposte

4 Alex.T Oct 02 2020 at 14:18

L'unico modo in cui posso pensare di farlo funzionare (a causa delle limitazioni di java switch) è creare una funzione di supporto nella classe enum stessa che ci consentirà di tradurla Idin un'enumerazione Value.

La funzione java sarebbe:

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 la classe enum sarebbe simile a questa:

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

Un altro modo per scrivere la funzione fromInt () sarebbe:

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
}

La seconda opzione non è così leggibile, ma è meglio se abbiamo molti valori enum