CodeBlanks Logo Icon CodeBlanks

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.

Practice 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()).

Starter code

Main.kt
data class Book(val title: String, val author: String, val year: Int, val category: Category) {
    fun format(): String = "$title - $author ($year) [${category.label()}]"
}

// Define Category sealed class: Fiction and NonFiction object subtypes
// label() method: Fiction returns "Fiction", NonFiction returns "Non-fiction"
// main: create one Fiction and one NonFiction book and print format output
fun main() {
    // write here
}

Sample solution

Main.kt
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())
}

Expected output

Crime and Punishment - Dostoyevsky (1866) [Fiction]
Sapiens - Harari (2011) [Non-fiction]

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What advantage does a sealed class provide?

  • Unlimited subtypes
  • Less memory usage
  • Faster compilation
  • Bounded subtypes and when exhaustiveness Correct answer

Explanation: A sealed class provides bounded subtypes and exhaustiveness in when.

2 Declare a sealed class

Question
____ class Category {
    abstract fun label(): String
}
Answer
sealed class Category {
    abstract fun label(): String
}

Explanation: sealed class Category sets up a bounded hierarchy.

3 Match the Category parts

Term Meaning
sealed class Category Bounded hierarchy
object Fiction Singleton subtype
override fun label() Label method
"Fiction" Fiction label

All lessons in Intermediate