CodeBlanks Logo Icon CodeBlanks

Putting it together

Combine all parts into a working final app.

Putting it together: the full flow

In the final lesson you combine all pieces: adding tasks, completing one and printing the completed ones. The app becomes a small sample of a real task tracker.

val list = TaskList()
list.addTask("Study Kotlin")
list.addTask("Shopping")
list.complete(0)
println(list.listDone())
// [[x] Study Kotlin]

This flow calls addTask, complete and listDone one after another. Each is a piece you defined in previous lessons. This completes a real use case.

Flow design

The app flow is: first add tasks to the list, then complete one, finally print the completed ones. Each step calls a method defined in earlier lessons.

list.addTask("Study Kotlin")    // L02
list.addTask("Shopping")        // L02
list.complete(0)                 // L04
println(list.listDone())         // L03

This flow shows the power of cumulative design. Each lesson added one piece and the final lesson put them together. In the real world, apps grow this way too.

Practice Combine the whole flow

In main create val list = TaskList(). Call list.addTask("Study Kotlin") and list.addTask("Shopping"). Complete the first task with list.complete(0). Finally print list.listDone() with println.

Starter code

Main.kt
class Task(val title: String) {
    var done: Boolean = false
    override fun toString(): String {
        return if (done) "[x] $title" else "[ ] $title"
    }
}

class TaskNotFound(message: String) : Exception(message)

class TaskList {
    val tasks = mutableListOf<Task>()
    fun addTask(title: String) {
        tasks.add(Task(title))
    }
    fun listDone() = tasks.filter { it.done }
    fun complete(index: Int) {
        if (index >= tasks.size) throw TaskNotFound("Görev yok: $index")
        tasks[index].done = true
    }
}

fun main() {
    val list = TaskList()
    // Add two tasks, complete one, print the done ones
}

Sample solution

Main.kt
class Task(val title: String) {
    var done: Boolean = false
    override fun toString(): String {
        return if (done) "[x] $title" else "[ ] $title"
    }
}

class TaskNotFound(message: String) : Exception(message)

class TaskList {
    val tasks = mutableListOf<Task>()
    fun addTask(title: String) {
        tasks.add(Task(title))
    }
    fun listDone() = tasks.filter { it.done }
    fun complete(index: Int) {
        if (index >= tasks.size) throw TaskNotFound("Görev yok: $index")
        tasks[index].done = true
    }
}

fun main() {
    val list = TaskList()
    list.addTask("Study Kotlin")
    list.addTask("Shopping")
    list.complete(0)
    println(list.listDone())
}

Expected output

[[x] Kotlin çalış]

Questions and answers

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

1 Match method to purpose

Term Meaning
addTask Add task
complete Finish task
listDone Get done tasks
TaskNotFound Error type

2 How are branches chosen in this project?

  • Only for
  • Only if
  • with when branches Correct answer
  • Only try

Explanation: The project flow uses when branches.

3 Fill in the blank: call complete

Question
try {
    list.____(0)
} catch (e: TaskNotFound) {
    println(e.message)
}
Answer
try {
    list.complete(0)
} catch (e: TaskNotFound) {
    println(e.message)
}

Explanation: list.complete(0) completes the first task.

All lessons in Beginner