Kotlin inline class — a use case

One of the use cases why an inline class is useful.

Bob Dahlberg
2 min readJan 14, 2020
Photo by Liao Je Wei on Unsplash

A while back, before Kotlin introduced inline classes, I was building a small widget that needed to convert Fahrenheit to Celsius and vice versa.

Since both are represented by a Double, I thought I’d use type aliases to separate them. I thought it was a cool idea, so I fired away and declared my type aliases and built functions to convert them as well.

typealias Fahrenheit = Double
typealias Celsius = Double
fun convert(value: Fahrenheit): Celsius = TODO()
fun convert(value: Celsius): Fahrenheit = TODO()

The first problem, you can’t do this. The Kotlin compiler can’t differentiate the two signatures from each other. The same thing applies to a when statement. As long as the value is a Double, it will always yield true on the Fahrenheit statement. The compiler will also say “Duplicate label in when” for the two type aliases.

return when(value) {
is Fahrenheit -> TODO()
is Celsius -> TODO()
}
// The above is actually resulting in this:
return when(value) {
is Double -> TODO()
is Double -> TODO()
}

Fair enough, onto the next attempt, extension functions. And now, the semantics of my function has a distinction that pleases the compiler.

fun Fahrenheit.toCelsius(): Celsius = TODO()
fun Celsius.toFahrenheit(): Fahrenheit = TODO()

So now, I can do pretty sweet code, and it’s clear what is what when reading the code. But it’s all up to the developer, and not enforced in any way by the code or structure.

val temperature: Fahrenheit = 0.0
val temperature2 = temperature.toFahrenheit()

We could chain “toFahrenheit” or “toCelsius” forever and ever without getting any code errors, only ending up with erroneous values.

So at this time, I gave up and filed a suggestion to Kotlin lang to fix the type aliases to be enforced. And they thought it was a bad idea for type aliases. A year or so later inline class feature was announced, and I finally was able to write the idiomatic code I wanted back then. Here’s how:

inline class Fahrenheit(val degree:Double)
inline class Celsius(val degree:Double)
fun convert(degree: Fahrenheit): Celsius = TODO()
fun convert(degree: Celsius): Fahrenheit = TODO()
fun Fahrenheit.toCelsius(): Celsius = TODO()
fun Celsius.toFahrenheit(): Fahrenheit = TODO()
val temperature = Fahrenheit(0.0)
val c = temperature.toCelsius() // can't call toFahrenheit here

Now let’s hope it makes it out of experimental soon. https://kotlinlang.org/docs/reference/inline-classes.html#experimental-status-of-inline-classes

There are, at the moment, a few restrictions to inline classes. But that’s another story. If you are eager to start, here is the official docs: https://kotlinlang.org/docs/reference/inline-classes.html

Thank you for your time!
→ Bob

--

--

Bob Dahlberg

Lead Developer at Qvik, Coach, Agile Thinker, GDG Lead.