# Sealed classes and 'when' expression

‘when’ expression as pattern-matching in Kotlin

Let’s consider the following case. You need to return 3 different return values from a function. Each value is associated with information. Say we do authentication and authorization in one shot. The results are:

• not authenticated + error message
• not authorized + userId + error message
• authenticated and authorized + userId

Algebraic data types looks the best fit here, but we have no such in Java.

A possible approach is to use enum for that. But enum does not allow us to pass additional information with each call. To fix that we may return a value object with all fields, but it will add a level of mess to the callee code.

Yet another apporach is to make the method return a base class or interface and to have an implementation per return case. This would make code cleaner, but with a cost of instenceof or visitor pattern impementation.

A nice thing in Kotlin is we are able to use when expression to make this checking code read better. In a recent post I covered when expression benefits.

We may also make sure we check all possible branchs in when expression. For this we only need to use sealed classes for return objects hierarchy.

This is example implementation code with sealed class and when expression:

In this example we also need not specify else case for when expression. Kotlin compiler is able to prove we listed all types if this sealed class.

Thanks to smart casts in each when branch we use exactly matched type, so for example, r.message in the first branch is NotAuthenticated#message and so on.

# Generated bytecode

Let’s traditionally take a look into bytecode, that was generated from this code snippet. Note. I use IntelliJ IDEA 2017.1 EAP with Kotlin 1.0.6 plugin. The generated bytecode may change with a future version of tools.

Kotlin compiler generated an if-else chain with instanceof checks. First it checks if the value is AuthResult$NotAuthenticated, next AuthResult$NotAuthorized and finally AuthResult\$Success. In a case something went terribly wrong, a kotlin.NoWhenBranchMatchedException exception is thrown. And this can be achieved if older version of our snippet is executed with a newer version of AuthResult class. A full re-compile will fail with error so we were able to fix the problem easily.

# Conclusion

In this post, we looked how when expression is working with sealed classes, which are really nice to use for cases, where one needs to return several different unrelated values.

# Related work

You may also like to read a related blog post Algebraic Data Types In Kotlin