I'm creating a Kotlin structure that I intend to reuse in several Android games with a similar format: a single grid with multiple cells. Depending on the game, the cells will have a different set of possible states. The set of states will be an Enum, but the contents will vary from game to game.
So I want a structure like:
class Cell(var state: Enum) {
...
}
where the state
parameter will be something different for each game.
For instance,
enum class TicTacToeState{
BLANK, X, O
}
val cell = Cell(TicTacToeState.BLANK)
or
enum class SeaBattleState{
BLANK, END, SUB, WATER
}
val cell = Cell(SeaBattleState.SUB)
The problem is when I type the structure at the top, Android Studio tells me, "One type argument expected for class Enum<E : Enum>".
I can't imagine what type I should call the Enum since I don't know what the contents will be, nor what type "BLANK" even is in the the context of an ENUM value. I've searched Google and here, but can't find any pages that deal in the class name Enum
with a type declaration, as opposed to the lowercase enum
to declare a class as an Enum.
So my question is, how do I declare a Kotlin class with a parameter of type Enum when I don't know yet what any of the Enums will be?
First of all, you need to be aware Enum
type is a little confusing at first in Java/Kotlin, because it is parameterized against itself. This adds some complexity to a case which we expect to be simple.
If we don't care what's the exact type of the enum, we could use Enum<*>
:
class Cell(val state: Enum<*>)
This is a direct equivalent of your code.
However, this is not very useful. If we have a Cell
, we can get its enum value, we can check ordinal and name of the enum, but we don't know what is this enum type exactly, we can't switch/when
on it easily, etc.:
val s = when (cell.state) {
TicTacToeState.BLANK -> ""
TicTacToeState.X -> "X"
TicTacToeState.O -> "O"
}
In the above case, IntelliJ won't help us find possible values for the state. Also, above code doesn't compile, because the compiler doesn't understand the when
is exhaustive. We would have to cast to TicTacToeState
manually.
In order to know the enum type, we have to make the Cell
generic. However, this is a little more complicated than usual, because of what was said at the beginning. We have to create a type parameter which is an enum targeting the same type. It's easier to do than explain:
class Cell<T : Enum<T>>(val state: T)
With this code, we don't just get a Cell
, we have Cell<TicTacToeState>
and the type of the enum is known to the compiler.