Kotlin / Java verwenden enum in einer switch-Anweisung vom Typ Int

Oct 02 2020

Für ein Android-Projekt habe ich eine .kt-Datei:

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

Und eine Java-Datei, in der das Problem auftritt:

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

Auf dem .Idgibt es einen Fehler 'ID hat privaten Zugriff in foo.animal', so dass das nicht funktioniert.

Wenn Sie .Idin .getId()ändern, wird aufgrund der switch-Anweisung 'Konstanter Ausdruck erforderlich' angezeigt.

Es ist eine Anforderung außerhalb meiner Kontrolle, dass der Typ intanstelle animalder Signatur ist, public void processAnimal(int animalId) {und dies wäre die richtige Lösung, wenn er nicht außerhalb meiner Kontrolle wäre.

Das Markieren von Feldern als öffentlich in der .kt-Datei ändert nichts.

Gibt es eine Möglichkeit, das zu erreichen, was ich mir vorgenommen habe?

Vielen Dank!

Antworten

4 Alex.T Oct 02 2020 at 14:18

Die einzige Möglichkeit, diese Funktion (aufgrund der Einschränkungen des Java-Schalters) zum Laufen zu bringen, besteht darin, eine Hilfsfunktion in der Enum-Klasse selbst zu erstellen, mit der wir diese Idin eine Enum übersetzen können Value.

Die Java-Funktion wäre:

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

Und die Enum-Klasse würde ungefähr so ​​aussehen:

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

Eine andere Art, diese fromInt () -Funktion zu schreiben, wäre:

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
}

Die zweite Option ist nicht so lesbar, aber besser, wenn wir viele Enum-Werte haben