Extension Function Best Practices
In this page:
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
fun String.isValidEmail(): Boolean = this.contains("@") && this.contains(".")
fun main() {
println("[email protected]".isValidEmail())
println("not-an-email".isValidEmail())
}
Login to try C/C++/Java/PHP code in the editor
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
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)
}
Login to try C/C++/Java/PHP code in the editor
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
fun Collection<Int>.sumOfSquares(): Int = this.sumBy { it * it }
fun main() {
println(listOf(1, 2, 3).sumOfSquares())
}
Login to try C/C++/Java/PHP code in the editor
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
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))
}
Login to try C/C++/Java/PHP code in the editor
- Adding extension functions with overly generic names on very broad types (like
Any), risking name clashes and confusing autocomplete suggestions. - Putting extensions with side effects that surprise callers, since an extension looks just like a normal member function at the call site.
- Scattering extension functions across many unrelated files instead of grouping related ones together for discoverability.
- 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: