Ed Pavlov
Ed Pavlov

Reputation: 2508

How do I declare a variable of enum type in Kotlin?

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

Answers (4)

Sam
Sam

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

Jayson Minard
Jayson Minard

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

Angel G. Olloqui
Angel G. Olloqui

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

user2235698
user2235698

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

Related Questions