Kotlin
OOP model
Set up the class hierarchy and interfaces.
Sealed class: Category
To sort books into categories you will define a sealed class. A sealed class sets up a hierarchy with a limited number of subtypes; it provides exhaustiveness in when expressions. Here you will use two categories: Fiction and NonFiction.
sealed class Category {
abstract fun label(): String
}
object Fiction : Category() {
override fun label() = "Fiction"
}
Each subtype (an object) inherits from Category and implements the label method. An object declares a singleton; there is exactly one instance per category. The Book class will get a category: Category property and format will show the category label.
Adding category to Book
The Book class gets a category: Category property. The format method also shows the category label: "$title - $author ($year) [${category.label()}]". So the book type appears in the output too.
val b = Book("Crime and Punishment", "Dostoyevsky", 1866, Fiction)
println(b.format())
// Crime and Punishment - Dostoyevsky (1866) [Fiction]
Here the Fiction object is given as the category; label() returns "Fiction". Thanks to the sealed class, the compiler knows that Category is only Fiction and NonFiction; this provides safety in when expressions. To add a new category later, just add a new object to the sealed class.
Exercise Combine Category sealed class and Book
The provided Book class already includes the category: Category property. Define sealed class Category; inside it add abstract fun label(): String. Define object Fiction : Category() and object NonFiction : Category(); each overrides label() (Fiction returns "Fiction", NonFiction returns "Non-fiction"). In main create one Fiction and one NonFiction book and print with println(b.format()).
Show example solution
data class Book(val title: String, val author: String, val year: Int, val category: Category) {
fun format(): String = "$title - $author ($year) [${category.label()}]"
}
sealed class Category {
abstract fun label(): String
}
object Fiction : Category() {
override fun label() = "Fiction"
}
object NonFiction : Category() {
override fun label() = "Non-fiction"
}
fun main() {
val b1 = Book("Crime and Punishment", "Dostoyevsky", 1866, Fiction)
val b2 = Book("Sapiens", "Harari", 2011, NonFiction)
println(b1.format())
println(b2.format())
}
Test yourself
-
What advantage does a sealed class provide?
- Unlimited subtypes
- Less memory usage
- Faster compilation
- Bounded subtypes and when exhaustiveness
Show answer
Bounded subtypes and when exhaustiveness — A sealed class provides bounded subtypes and exhaustiveness in when.
-
Declare a sealed class
____ class Category {
abstract fun label(): String
}
Show answer
sealed class Category {
abstract fun label(): String
}
-
Match the Category parts
- sealed class Category
- Bounded hierarchy
- object Fiction
- Singleton subtype
- override fun label()
- Label method
- "Fiction"
- Fiction label
Next lesson: Collections