Introduction
Extension functions let you add new functions to existing classes, including classes you don't own or can't modify, such as those from the standard library or third-party code. Instead of inheriting from a class or using a wrapper, you define a function outside the class that appears to be a member of it. This is a purely syntactic feature: the class itself is never modified, and no new members are actually inserted into it.
Cricket analogy: Commentators unofficially label a bowler's signature delivery the doosra without the ICC rulebook itself being rewritten; an extension function similarly lets you call String.lastChar() without ever touching Kotlin's own String class source.
Syntax
fun String.lastChar(): Char = this[this.length - 1]
// Called just like a member function
val c = "hello".lastChar()Explanation
The type before the dot (String) is called the receiver type — the type being extended. Inside the function body, this refers to the receiver instance, in this case the string the function was called on. Once declared, lastChar() can be called on any String value exactly as if it were a real member function. An important gotcha is that extension functions are resolved statically at compile time based on the declared type of the expression, not the actual runtime type — this means they do NOT participate in true polymorphism or virtual dispatch the way member function overrides do.
Cricket analogy: Once a scorer decides a batsman is the striker (the receiver), all further ball-by-ball notes use this batsman to mean him specifically, but the decision is locked in before the ball is bowled, not adjusted mid-delivery, just as extension functions resolve to the declared type at compile time.
Example
fun String.lastChar(): Char = this[this.length - 1]
fun Int.isEven(): Boolean = this % 2 == 0
open class Animal
class Dog : Animal()
fun Animal.describe() = "an Animal"
fun Dog.describe() = "a Dog"
fun printDescription(animal: Animal) {
println(animal.describe())
}
fun main() {
println("hello".lastChar())
println(4.isEven())
printDescription(Dog())
}Output
o
true
an AnimalKey Takeaways
- Extension functions are declared as
fun ReceiverType.functionName(): ReturnType. - Inside the function,
thisrefers to the receiver instance. - They let you add functions to classes without modifying source code or using inheritance.
- Extension functions are resolved statically, based on the declared (compile-time) type, not the runtime type.
- Because of static resolution, extension functions do NOT support true polymorphic/virtual dispatch.
Practice what you learned
1. How is an extension function declared for the `String` class?
2. Inside an extension function, what does `this` refer to?
3. Why is it important that extension functions are resolved statically at compile time?
4. Does declaring an extension function modify the original class's source code?
Was this page helpful?
You May Also Like
Higher-Order Functions in Kotlin
Learn how Kotlin functions can accept or return other functions, enabling flexible, reusable, functional-style code.
Lambda Expressions in Kotlin
Understand how to write and use lambda expressions in Kotlin, including trailing lambda syntax and the implicit it parameter.
Classes in Kotlin
Learn how Kotlin classes bundle state and behavior with concise constructor syntax and final-by-default semantics.
Inheritance in Kotlin
Learn how open classes, open members, and the override keyword enable single-class inheritance in Kotlin.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics