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);
}
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.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With