Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Circular reference in Kotlin Enum

How can I create an enum class with circular references?

Simple example (taken from this Java question):

enum class Hand(val beats: Hand) {
    ROCK(SCISSORS), // Enum entry 'SCISSORS' is uninitialized here
    PAPER(ROCK),
    SCISSORS(PAPER);
}
like image 337
Michael Hoff Avatar asked Feb 21 '18 15:02

Michael Hoff


2 Answers

As reassignment is forbidden for val properties, this problem is generally hard to solve and often indicates problems in your data model. For a discussion in broader context refer to this question/answer(s).

However, this simple example can be solved using a val property with custom getter (thus without a backing field). Using when, the getter can be defined in a very readable way:

enum class Hand {
    ROCK,
    PAPER,
    SCISSORS;

    val beats: Hand
        get() = when (this) {
            ROCK -> SCISSORS
            PAPER -> ROCK
            SCISSORS -> PAPER
        }
}

An alternative solution (analogue to the answer by Eugen Pechanec) is to use sealed classes. Due to their less constrained concept, the implementation is1 slightly simpler and more readable compared to an enum with overridden properties.

sealed class Hand {
    abstract val beats: Hand

    object ROCK: Hand() {
        override val beats = SCISSORS
    }

    object PAPER: Hand() {
        override val beats = ROCK
    }

    object SCISSORS: Hand() {
        override val beats = PAPER
    }
}

1personal opinion

Disclaimer: I have no information on how these solutions work in conjunction with classic Java.

like image 137
Michael Hoff Avatar answered Nov 02 '22 13:11

Michael Hoff


An alternative to mhoff's answer without flow control statements:

enum class Hand {
    ROCK {
        override val beats: Hand
            get() = SCISSORS
    },
    PAPER {
        override val beats: Hand
            get() = ROCK
    },
    SCISSORS {
        override val beats: Hand
            get() = PAPER
    };

    abstract val beats: Hand
}
like image 7
Eugen Pechanec Avatar answered Nov 02 '22 15:11

Eugen Pechanec