:wave: I wanted to see what the community thinks a...
# kotlin-native
z
đź‘‹ I wanted to see what the community thinks about enums in Kotlin. I had a discussion with a colleague and I learned that enums seem to be taking a back seat to sealed classes and interfaces. I was really surprised given that I come from a Swift background where enums are very important and widely used.
j
Swift enums and other language's enums (such as Rust) are far closer to sealed hierarchies than Kotlin's extremely basic, JVM-inspired(/limited) version of enums
e
since you're familiar with Swift: JVM enums cannot have associated values
so while Swift's
Copy code
enum Foo {
    case bar, baz
}
is mostly equivalent to
Copy code
enum class Foo {
    bar, baz
}
you can't translate
Copy code
enum Foo {
    case bar(Int)
    case baz
}
to a Kotlin
enum class
z
I see.. I understand now. Enums in Kotlin are not equal to Swift in Kotlin.
e
that would be more closely represented by
Copy code
sealed class Foo {
    data class Bar(val value: Int) : Foo()
    object Baz : Foo()
}
instead. of course you could also translate an
enum
without associated values to `sealed class`+`object`, but while the usage is pretty similar in Kotlin, you lose some of the Java conveniences of
enum
that way
k
Is there much difference on a machine code / bytecode level? I assume enums are better because it doesn’t require virtual dispatch whereas sealed hierarchies would. I don’t know if there’s other ancillary benefits too, though
e
there is a bit of a difference in bytecode, yes. virtual dispatch is… maybe confusing
j
enums are basically sealed value classes. so once we get those enums will mostly be obsolete aside from a syntactical terseness where they have an implicit backing integer and auto-assigned ordinals
k
That’s a good point — referring to an instance of an enum by it’s ordinal is often a footgun. Especially for things like db persistence.
j
although sealed value classes can still box whereas enums are always boxed-by-default. you pass around the reference rather than the underlying ordinal. so still slightly different
e
Copy code
enum class Foo {
    Bar,
    Baz {
        override fun toString(): String = "baz"
    }
}
in bytecode this looks sorta like what
Copy code
class Foo private constructor(override val name: String) : Enum<Foo> {
    override fun toString(): String = name

    private class Baz(name: String) : Foo(name) {
        override fun toString(): String = "baz"
    }

    companion object {
        @JvmField
        val Bar = Foo("bar")
        @JvmField
        val Baz = Baz("baz")
        @JvmStatic
        fun values(): Array<Foo> = arrayOf(Bar, Baz)
    }
}
would compile to, except that you aren't allowed to subclass
Enum
yourself
(plus some other enum magic like ordinal and valueOf)
z
This is really helpful, thanks!