Kotlin vs Swift — Enumeration

I love programming in Android and iOS platforms with Kotlin and Swift, I will demonstrate the difference and similarity of enumeration using code in this post, it is part of this language comparison series.

Definition of Enumeration

In Kotlin, each enum constant is an object.

enum class Direction { 
NORTH, SOUTH, WEST, EAST
}

Swift

But in Swift, an enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code. Each enum case is a value.

enum Direction {
case north
case south
case west
case east
}

enum Direction {
case north, south, west, east
}

Represent values

In Kotlin, each enum is an instance of the enum class. Int or String values can be represented by parameters of the primary constructor of the enum class.

enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}

enum class Color(val rgb: String) {
RED("0xFF0000"),
GREEN("0x00FF00"),
BLUE("0x0000FF")
}

val color = Color.RED
val rgb = color.rgb

But in Swift, if a value (known as a raw value) is provided for each enumeration case, the value can be a string, a character, or a value of any integer or floating-point type. The value is represented by raw value rather than an extra parameter in Kotlin.

enum Color : Int {
case red = 0xFF0000
case gree = 0x00FF00
case blue = 0x0000FF
}

enum Color : String {
case red = "0xFF0000"
case gree = "0x00FF00"
case blue = "0x0000FF"
}

val color = Color.red
val rgb = color.rawValue

Anonymous class

In Kotlin, enum constants can also declare their anonymous classes with their corresponding methods, as well as overriding base methods. The anonymous class appended on the enum instance is a great place with the ability to extend the enum instance.

enum class ProtocolState {
WAITING {
override fun signal() = TALKING
},

TALKING {
override fun signal() = WAITING
};

abstract fun signal(): ProtocolState
}

val state = ProtocolState.WAITING.signal()

But in Swift, enum case is an atom, but we can implement a similar function in enum type using switch case.

enum ProtocolState {
case waiting, talking

func signal() -> ProtocolState {
switch self {
case .waiting:
return .talking
case .talking:
return .waiting
}
}
}

let state = ProtocolState.waiting.signal()

Implementing Interfaces

In Kotlin, an enum class may implement an interface (but not derive from a class), providing either a single interface members implementation for all of the entries.

enum class IntArithmetics : BinaryOperator<Int> {
PLUS,
TIMES;

override fun apply(t: Int, u: Int) =
when (this) {
PLUS -> {
t + u
}
TIMES -> {
t * u
}
}
}

IntArithmetics.PLUS.apply(13, 31)

or separate ones for each entry within its anonymous class.

enum class IntArithmetics : BinaryOperator<Int> {
PLUS {
override fun apply(t: Int, u: Int): Int = t + u
},
TIMES {
override fun apply(t: Int, u: Int): Int = t * u
};
}

But in Swift, there is no anonymous class like Kotlin, but enum type is good enough to implement any protocol using switch case. If you don’t like the long-winded switch like me, unfortunately, there is no better way to do it.

enum IntArithmetics: IntBinaryOperator {
case plus, times

func apply(_ t: Int, _ u: Int) -> Int {
switch self {
case .plus:
return t + u
case .times:
return t * u
}
}
}

IntArithmetics.plus.apply(13, 31)
IntArithmetics.times.apply(13, 31)

Working with Enum Constants

In Kotlin, enum classes have synthetic methods allowing valueOf(value:) to list the defined enum constants and values() to get an enum constant by its name.

enum class Direction {
NORTH, SOUTH, WEST, EAST
}

Direction.valueOf(value="NORTH") //Direction.NORTH
Direction.values() //Array<Direction>

Direction.NORTH.name

And since Kotlin 1.1, it’s possible to access the constants in an enum class in a generic way.

enumValueOf<Direction>(name="NORTH") //Direction.NORTH
enumValues<Direction>() //Array<Direction>

Those implicit and auto-generated api are very handy if you read the official document carefully.

But in Swift, enum can be constructed only if the enum derives from a class. the derivation provides both raw value and accessible initializer EnumType(rawValue:). Enum cases can be iterated with the help of CaseIterable protocol. Comparing with Kotlin, Swift need to be more explicit.

enum Direction : String, CaseIterable {
case north, south, west, east
}

Direction(rawValue: "north") //Direction.north
Direction.allCases

Direction.north.rawValue

Superclass

In Kotlin, Enum class is the common base class of all enum classes.

abstract class Enum<E : Enum<E>> : Comparable<E>

But in Swift, there is no common base class for enum type.

Shorter dot syntax

In Kotlin, there is no shorter dot syntax when using enum.

But in Swift, the type of directionToHead is inferred when it’s initialized with one of the possible values of Direction. Once directionToHead is declared as a Direction, you can set it to a different Direction value using shorter dot syntax.

var directionToHead = Direction.west
directionToHead = .east

Implicitly Assigned Raw Values

In Kotlin, if enum class has one primary constructor, all enum instance have to call it explicitly.

enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}

But in Swift, when you’re working with enumerations that store integer or string raw values, you don’t have to explicitly assign a raw value for each case. When you don’t, Swift automatically assigns the values for you.

enum Planet: Int {
case mercury = 1, venus, earth
}

In the example above, Planet.mercury has an explicit raw value of 1, Planet.venus has an implicit raw value of 2, and so on.

Associated Values

In Kotlin, enum instances have the same parameters come from the primary constructor, it restricts all instances need to be in the same structure. But in some sense, instances may have different structures with others. We have to ask the sealed class for help.

sealed class Barcodedata class Upc(val number1: Int, val number2: Int, val number3: Int, val number4: Int) : Barcode()data class QrCode(val code: String) : Barcode()

But in Swift, enumeration cases can specify associated values of any type to be stored along with each different case value.

enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}

Recursive Enumerations

A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases.

In Kotlin, we already know when the set of value is restricted like enum instance and they have its own structure, we can use sealed class rather than enum class.

sealed class ArithmeticExpressiondata class Number(val value: Int) : ArithmeticExpression()data class Addition(val exp1: ArithmeticExpression, val exp2: ArithmeticExpression) : ArithmeticExpression()data class Multiplication(val exp1: ArithmeticExpression, val exp2: ArithmeticExpression) : ArithmeticExpression()val sum = Addition(Number(5), Number(4))
val product = Multiplication(sum, Number(2))

But in Swift, enum supports this feature in language level.

indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}

Summary of Enumeration

Kotlin

  • enum case is an instance (an object) of enum class
  • represents value using primary constructor
  • enum instance can be extended using anonymous classes👏
  • Kotlin compiler generates synthetic methods implicitly
  • enum = enum class + sealed class

Swift

  • enum case is a value of enum type👏
  • represents value using deriving from the type of value
  • enum case is an atom, extend them in parent (enum type) using switch
  • please explicitly in Swift👏
  • enum = enums, even associating value and recursion👏

I give 👏 to some enum features of Kotlin and Swift personally, and I love both of them, especially when you realise the genius idea of language design from different aspect. If you like this post, please share and stay awesome.

Mobile developer@NZ. iOS, Android, React

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store