Reputation: 2508
Following the documentation, I created an enum class:
enum class BitCount public constructor(val value : Int)
{
x32(32),
x64(64)
}
Then, I'm trying to declare a variable in some function:
val bitCount : BitCount = BitCount(32)
But there is a compilation error:
Error:(18, 29) Kotlin: Enum types cannot be instantiated
How do I declare a variable of BitCount type and initialize it from an Int
?
Upvotes: 39
Views: 41448
Reputation: 9944
If you really do want to give the ability to construct arbitrary instances, use a value class instead of an enum.
@JvmInline value class BitCount(val value: Int) {
companion object {
val x32 = BitCount(32)
val x64 = BitCount(64)
}
}
Value classes are always compared by their value, rather than by identity. You can call BitCount(32)
, but the result will always be the same as the existing x32
instance, as there's only one possible instance with that value.
Using this approach, you can create any BitCount
value you like, for example BitCount(31)
or BitCount(-1)
. Use this approach if the set of possible values can vary at runtime or can't be practically represented by listing them all out in the code. Use an enum if you have a small, fixed set of allowed values that are known at compile-time.
Upvotes: 0
Reputation: 85946
As stated in other answers, you can reference any value of the enum
that exists by name, but not construct a new one. That does not prevent you from doing something similar to what you were trying...
// wrong, it is a sealed hierarchy, you cannot create random instances
val bitCount : BitCount = BitCount(32)
// correct (assuming you add the code below)
val bitCount = BitCount.from(32)
If you were wanting to find the instance of the enum
based on the numeric value 32
then you could scan the values in the following way. Create the enum
with a companion object
and a from()
function:
enum class BitCount(val value : Int)
{
x16(16),
x32(32),
x64(64);
companion object {
fun from(findValue: Int): BitCount = BitCount.values().first { it.value == findValue }
}
}
Then call the function to get a matching existing instance:
val bits = BitCount.from(32) // results in BitCount.x32
Nice and pretty. Alternatively in this case you could create the name of the enum
value from the number since you have a predictable relationship between the two, then use BitCount.valueOf()
. Here is the new from()
function within the companion object.
fun from(findValue: Int): BitCount = BitCount.valueOf("x$findValue")
Upvotes: 78
Reputation: 8105
What about:
enum class BitCount constructor(val value : Int)
{
x32(32),
x64(64);
companion object {
operator fun invoke(rawValue: Int) = BitCount.values().find { it.rawValue == rawValue }
}
}
Then you can use it like you proposed:
val bitCount = BitCount(32)
And it will return null if value is not found in enum cases
Upvotes: 8
Reputation: 7579
Enum instances could be declared only inside enum class declaration.
If you want to create new BitCount just add it as shown below:
enum class BitCount public constructor(val value : Int)
{
x16(16),
x32(32),
x64(64)
}
and use everywhere as BitCount.x16
.
Upvotes: 14