← Back to Kotlin Course | Chapter 10: Extension Functions & Properties | Lesson 6 of 6

Extension Function Best Practices

Best practices for extensions are the good habits that keep your bolted-on abilities clear and easy to find later, instead of scattered and confusing.

Naming Extensions Clearly

A good extension function name should read naturally at the call site and clearly describe what it does, avoiding vague names that could be confused with unrelated behavior.

Example: Naming Extensions Clearly

markup
fun String.isValidEmail(): Boolean = this.contains("@") && this.contains(".")

fun main() {
    println("[email protected]".isValidEmail())
    println("not-an-email".isValidEmail())
}

Avoiding Surprising Side Effects

Because an extension function looks exactly like a real member function to the caller, it should behave predictably -- avoid extensions that silently mutate shared state in surprising ways.

Example: Avoiding Surprising Side Effects

markup
fun MutableList<Int>.addIfPositive(value: Int): Boolean {
    return if (value > 0) {
        add(value)
        true
    } else {
        false
    }
}

fun main() {
    val numbers = mutableListOf(1, 2)
    numbers.addIfPositive(5)
    numbers.addIfPositive(-3)
    println(numbers)
}

Scoping Extensions to Specific Types

Writing an extension against the narrowest type that makes sense (rather than a very broad type like Any) keeps it relevant and avoids cluttering autocomplete suggestions for unrelated types.

Example: Scoping Extensions to Specific Types

markup
fun Collection<Int>.sumOfSquares(): Int = this.sumBy { it * it }

fun main() {
    println(listOf(1, 2, 3).sumOfSquares())
}

Grouping Related Extensions Together

Organizing extension functions that relate to the same type or feature area into one clearly named file makes them easy for other developers (and your future self) to find.

Example: Grouping Related Extensions Together

markup
fun String.truncate(maxLength: Int): String =
    if (this.length <= maxLength) this else this.take(maxLength) + "..."

fun String.titleCase(): String =
    this.split(" ").joinToString(" ") { it.capitalize() }

fun main() {
    println("kotlin programming language".titleCase())
    println("This is a long sentence".truncate(10))
}
Common Mistakes
  1. Adding extension functions with overly generic names on very broad types (like Any), risking name clashes and confusing autocomplete suggestions.
  2. Putting extensions with side effects that surprise callers, since an extension looks just like a normal member function at the call site.
  3. Scattering extension functions across many unrelated files instead of grouping related ones together for discoverability.
Chapter Summary
  • Keep extension functions focused, well-named, and scoped to as specific a type as makes sense.
  • Avoid extensions with confusing side effects, since call sites cannot tell an extension apart from a real member at a glance.
  • Group related extension functions together in a clearly named file so they are easy to discover and maintain.
  • Prefer extensions for genuinely reusable, general-purpose helpers rather than one-off logic specific to a single use case.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.