Extension Functions Workbook


Practice problems for Extension Functions: Add Methods to Classes You Don’t Own. Each takes a minute or two. Write your own answer first, then click Show answer — nothing here is a trick question, just direct practice of the syntax from the lesson.

declaring extensions

1. Extend String

Write an extension shout() on String that returns the uppercased text with a ! appended.

Show answer Hide answer
fun String.shout() = uppercase() + "!"

"hello".shout()   // "HELLO!"

this (the receiver) is implicit, so uppercase() reads like a member call.

2. Extend Int

Write an extension isEven() on Int returning whether it’s even.

Show answer Hide answer
fun Int.isEven() = this % 2 == 0

4.isEven()   // true

3. Extend a generic type

Write List<Int>.secondOrNull() that returns the second element, or null if the list is too short.

Show answer Hide answer
fun List<Int>.secondOrNull(): Int? = if (size >= 2) this[1] else null

properties and nullable receivers

4. An extension property

Write a read-only extension property firstWord on String returning everything before the first space.

Show answer Hide answer
val String.firstWord: String
    get() = substringBefore(" ")

"hello world".firstWord   // "hello"

An extension property has no backing field, so it must compute its value in a getter.

5. A nullable receiver

Write orEmpty() on String? that returns "" when the receiver is null, otherwise the string itself.

Show answer Hide answer
fun String?.orEmpty(): String = this ?: ""

val name: String? = null
name.orEmpty()   // ""

Extending a nullable type lets the extension handle null itself — the call is safe with no ?..

resolution rules

6. Make it polymorphic

Extensions resolve statically, so with fun Animal.speak() and fun Dog.speak(), a val pet: Animal = Dog() calls the Animal one. Rewrite speak as member functions so pet.speak() returns "woof".

Show answer Hide answer
open class Animal { open fun speak() = "generic" }
class Dog : Animal() { override fun speak() = "woof" }

val pet: Animal = Dog()
pet.speak()   // "woof" — members dispatch on the runtime type

7. Members win

Write a class Box with a member size() returning 1, plus an extension Box.size() returning 99. What does Box().size() return?

Show answer Hide answer
class Box { fun size() = 1 }
fun Box.size() = 99

Box().size()   // 1 — a member always wins over an extension

8. Chain reads top-to-bottom

Rewrite reversed(trimmed(input)) (two hypothetical helpers) as a readable extension chain input.trimmed().reversed() — just write the two extension signatures that make it possible.

Show answer Hide answer
fun String.trimmed() = trim()
fun String.reversed() = StringBuilder(this).reverse().toString()

Extensions let calls read in subject-verb order instead of inside-out.

9. Extend with a parameter

Write an extension repeatTimes(n: Int) on String returning the string concatenated n times.

Show answer Hide answer
fun String.repeatTimes(n: Int) = repeat(n)

10. Nullable receiver, used safely

Given name: String?, call your orEmpty() extension on it directly. Why is no ?. needed?

Show answer Hide answer
name.orEmpty()

Because the receiver type is String?, the extension itself accepts null — so the plain dot call is safe.


Back to the lesson, Extension Functions, or on to the next one: equality.