📖 Scenario: Imagine you are building a simple app that handles different types of notifications: Email, SMS, and Push notifications. Each notification type has its own data.
🎯 Goal: You will create sealed classes to represent these notification types and use a when expression to handle each type with an exhaustive check.
📋 What You'll Learn
Create a sealed class called Notification with three subclasses: Email, SMS, and Push
Add properties to each subclass as specified
Create a variable called notification with a specific subclass instance
Use a when expression with exhaustive check to handle all notification types
Print a message describing the notification
💡 Why This Matters
🌍 Real World
Sealed classes help represent fixed sets of related types, like different notification types in an app, making code safer and easier to maintain.
💼 Career
Understanding sealed classes and exhaustive <code>when</code> expressions is important for Kotlin developers building robust and clear applications.
Progress0 / 4 steps
1
Create sealed class and subclasses
Create a sealed class called Notification with three subclasses: Email with a subject property of type String, SMS with a phoneNumber property of type String, and Push with a message property of type String.
Kotlin
Hint
Use sealed class Notification and inside it define data class Email, SMS, and Push each inheriting from Notification.
2
Create a notification instance
Create a variable called notification and assign it an instance of Notification.Email with the subject set to "Welcome to Kotlin".
Kotlin
Hint
Use val notification: Notification = Notification.Email("Welcome to Kotlin") to create the instance.
3
Use when expression with exhaustive check
Write a when expression using the variable notification to handle all subclasses: Email, SMS, and Push. For each case, create a string message describing the notification. Assign the result to a variable called message. Make sure the when expression is exhaustive.
Kotlin
Hint
Use val message = when (notification) { ... } with all subclasses handled.
4
Print the message
Write a println statement to display the value of the variable message.
Kotlin
Hint
Use println(message) to display the message.
Practice
(1/5)
1. What is the main benefit of using sealed classes in Kotlin when combined with a when expression?
easy
A. The when expression becomes exhaustive, ensuring all cases are handled.
B. It allows subclassing from any file in the project.
C. It automatically generates getter and setter methods.
D. It makes the class open for inheritance everywhere.
Solution
Step 1: Understand sealed classes restriction
Sealed classes restrict subclassing to the same file, so all subclasses are known at compile time.
Step 2: Effect on when expression
This allows the when expression to be exhaustive because the compiler knows all possible subclasses.
Final Answer:
The when expression becomes exhaustive, ensuring all cases are handled. -> Option A
Quick Check:
Sealed classes + when = exhaustive check [OK]
Hint: Sealed classes limit subclasses, making when exhaustive [OK]
2. Which of the following is the correct syntax to declare a sealed class in Kotlin?
easy
A. sealed class Shape {}
B. open sealed class Shape {}
C. sealed interface Shape {}
D. final sealed class Shape {}
Solution
Step 1: Recall sealed class declaration syntax
In Kotlin, sealed classes are declared with the keyword sealed followed by class and the class name.
Step 2: Check options for correctness
sealed class Shape {} uses correct syntax: sealed class Shape {}. open sealed class Shape {} incorrectly adds open, which is not allowed. sealed interface Shape {} uses sealed interface, which is invalid. final sealed class Shape {} uses final sealed class, which is not allowed.
Final Answer:
sealed class Shape {} -> Option A
Quick Check:
sealed class declaration = sealed class Shape {} [OK]
Hint: Use only 'sealed class ClassName' to declare sealed classes [OK]
Common Mistakes:
Adding 'open' modifier to sealed class
Trying to declare sealed interfaces (not allowed)
Using 'final' modifier with sealed class
3. Given the sealed class hierarchy below, what will be the output of the describe function when called with Shape.Circle(5.0)?
sealed class Shape {
data class Circle(val radius: Double) : Shape()
data class Rectangle(val width: Double, val height: Double) : Shape()
}
fun describe(shape: Shape): String = when(shape) {
is Shape.Circle -> "Circle with radius ${shape.radius}"
is Shape.Rectangle -> "Rectangle with width ${shape.width} and height ${shape.height}"
}
medium
A. Rectangle with width 5.0 and height 5.0
B. Compilation error due to missing else branch
C. Shape.Circle
D. Circle with radius 5.0
Solution
Step 1: Identify the input and matching when branch
The input is Shape.Circle(5.0). The when expression matches is Shape.Circle branch.
Step 2: Evaluate the returned string
The branch returns the string "Circle with radius 5.0" using the radius property.
Final Answer:
Circle with radius 5.0 -> Option D
Quick Check:
Input Circle(5.0) returns "Circle with radius 5.0" [OK]
Hint: Match input type in when to get correct output string [OK]
Common Mistakes:
Confusing Circle with Rectangle output
Expecting a compilation error due to else missing
Returning class name instead of formatted string
4. Consider the following code snippet. What is the error and how can it be fixed?
sealed class Result {
object Success : Result()
object Failure : Result()
}
fun handle(result: Result) = when(result) {
is Result.Success -> "Success"
}
medium
A. Runtime error: Result.Failure is not handled and causes crash.
B. Compilation error: when expression is not exhaustive; add branch for Result.Failure.
C. No error; code runs fine and returns null for Result.Failure.
D. Syntax error: sealed classes cannot have object subclasses.
Solution
Step 1: Identify the sealed class subclasses
Result has two subclasses: Success and Failure.
Step 2: Check when expression branches
The when expression only handles Result.Success, missing Result.Failure branch.
Step 3: Understand Kotlin's exhaustiveness check
Since Result is sealed, when must handle all subclasses or have an else branch. Missing Failure causes compilation error.
Final Answer:
Compilation error: when expression is not exhaustive; add branch for Result.Failure. -> Option B
Quick Check:
Sealed class when must cover all subclasses [OK]
Hint: Add all sealed subclasses in when to avoid errors [OK]
Common Mistakes:
Assuming runtime error instead of compile error
Ignoring missing branches in when
Thinking sealed classes can't have object subclasses
5. You have a sealed class Operation with subclasses Add, Subtract, and Multiply. Write a Kotlin function calculate that takes an Operation and two integers, and returns the result of applying the operation. Which of the following implementations correctly uses an exhaustive when expression?
hard
A. fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Add -> a + b
else -> 0
}
B. fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Add -> a + b
is Operation.Subtract -> a - b
}
C. fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Add -> a + b
is Operation.Subtract -> a - b
is Operation.Multiply -> a * b
}
D. fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Multiply -> a * b
else -> a + b
}
Solution
Step 1: Check all subclasses handled in when
Operation has Add, Subtract, Multiply. fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Add -> a + b
is Operation.Subtract -> a - b
is Operation.Multiply -> a * b
} handles all three explicitly.
Step 2: Verify exhaustiveness and correctness
fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Add -> a + b
is Operation.Subtract -> a - b
is Operation.Multiply -> a * b
} covers all subclasses, so when is exhaustive. The other options miss some subclasses or rely on else, which is less clear.
Final Answer:
fun calculate(op: Operation, a: Int, b: Int): Int = when(op) {
is Operation.Add -> a + b
is Operation.Subtract -> a - b
is Operation.Multiply -> a * b
} -> Option C
Quick Check:
All subclasses covered in when = exhaustive [OK]
Hint: Cover all sealed subclasses explicitly for exhaustive when [OK]
Common Mistakes:
Missing some subclasses in when branches
Using else instead of explicit branches
Returning wrong default values
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.