Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force compilation error with sealed classes

Tags:

kotlin

With sealed classes you can use exhaustive when expressions and omit the else clause when the expression returns a result:

sealed class SealedClass {   class First : SealedClass()   class Second : SealedClass() }  fun test(sealedClass: SealedClass) : String =     when (sealedClass) {       is SealedClass.First -> "First"       is SealedClass.Second -> "Second"     } 

Now if I were to add a Third to SealedClass, the compiler will complain that the when expression in test() is not exhaustive, and I need to add a clause for Third or else.

I am wondering however if this check can also be enforced when test() does not return anything:

fun test(sealedClass: SealedClass) {     when (sealedClass) {       is SealedClass.First -> doSomething()       is SealedClass.Second -> doSomethingElse()     } } 

This snippet does not break if Third is added. I can add a return statement before when, but this could easily be forgotten and may break if the return type of one of the clauses is not Unit.

How can I make sure I don't forget to add a branch to my when clauses?

like image 605
nhaarman Avatar asked Jul 03 '16 12:07

nhaarman


People also ask

Can you instantiate a sealed class?

Sealed classes cannot be instantiated directly. Sealed classes cannot have public constructors (The constructors are private by default). Sealed classes can have subclasses, but they must either be in the same file or nested inside of the sealed class declaration.

Can sealed classes be data?

What are sealed classes? Sealed classes represent a restricted class hierarchy. This allows you to define subclasses within the scope of the parent function, allowing you to represent hierarchies. In this case, the child or subclass can be of any type, a data class, an object, a regular class, or another sealed class.

What is a sealed class and give an example where to use them?

The main purpose of a sealed class is to take away the inheritance feature from the class users so they cannot derive a class from it. One of the best usage of sealed classes is when you have a class with static members. For example, the Pens and Brushes classes of the System.

What are sealed classes?

Sealed classes are used to restrict the users from inheriting the class. A class can be sealed by using the sealed keyword. The keyword tells the compiler that the class is sealed, and therefore, cannot be extended. No class can be derived from a sealed class.


2 Answers

The way to enforce exhaustive when is to make it an expression by using its value:

sealed class SealedClass {     class First : SealedClass()     class Second : SealedClass()     class Third : SealedClass() }  fun test(sealedClass: SealedClass) {     val x = when (sealedClass) {         is SealedClass.First -> doSomething()         is SealedClass.Second -> doSomethingElse()     }  // ERROR here      // or      when (sealedClass) {         is SealedClass.First -> doSomething()         is SealedClass.Second -> doSomethingElse()     }.let {}  // ERROR here } 
like image 186
voddan Avatar answered Sep 29 '22 21:09

voddan


In inspiration by Voddan's answer, you can build a property called safe you can use:

val Any?.safe get() = Unit 

To use:

when (sealedClass) {     is SealedClass.First -> doSomething()     is SealedClass.Second -> doSomethingElse() }.safe 

I think it provides a clearer message than just appending .let{} or assigning the result to a value.


There is an open issue on the Kotlin tracker which considers to support 'sealed whens'.

like image 41
nhaarman Avatar answered Sep 29 '22 22:09

nhaarman