Kotlin Extension Functions
Extension functions allow adding new behavior to existing classes, even sealed library classes like String or List, without inheritance or modifying their source code. They are resolved statically and do not actually change the original class.
Key Features
- Called with regular dot notation, look and feel like real member functions
- Can be added to any type: classes, interfaces, primitives, and nullable types
- Support extension properties (computed properties on existing types)
- Can be defined at top level, inside classes, or in companion objects
- Cannot access private or protected members of the target class
- Member functions always take precedence over extension functions with the same signature
How Extension Functions Work Internally
The Kotlin compiler transforms every extension function into a static function. The receiver object becomes the first parameter of that static function.
// Written in Kotlin
fun String.repeat(n: Int): String
// Becomes in bytecode (simplified)
static String repeat(String receiver, int n) { ... }
Examples
1. Extending Int
fun Int.timesEight() = this * 8
fun main() {
println(7.timesEight()) // 56
}
2. Extending a Custom Class
class Circle(val radius: Double) {
fun area() = Math.PI * radius * radius
}
fun Circle.diameter() = radius * 2
fun Circle.circumference() = 2 * Math.PI * radius
fun main() {
val c = Circle(4.0)
println(c.diameter()) // 8.0
println(c.circumference()) // ≈25.13
}
3. Nullable Receiver
fun String?.isNullOrBlank(): Boolean =
this == null || this.isBlank()
fun main() {
val s: String? = null
println(s.isNullOrBlank()) // true
}
4. Extension Property
val String.isLong: Boolean
get() = length >= 20
fun main() {
println("Kotlin is awesome".isLong) // false
}
Important Rules
- Resolved statically by the declared type, not the runtime type
- Just syntactic sugar, no runtime performance cost
- Member functions always win over extension functions with the same name
- Perfect for utilities, DSLs, and cleaner APIs
- Not suitable when private state access or true polymorphism is needed