Extension Functions
In this page:
Declaring an Extension Function
An extension function is written as fun Type.name(...), letting you call value.name(...) as if name were a real member of Type, even though Type's own source code was never touched.
Example: Declaring an Extension Function
fun String.shout(): String = this.toUpperCase() + "!"
fun main() {
println("hello".shout())
}
Login to try C/C++/Java/PHP code in the editor
Using this Inside an Extension
Within an extension function's body, this refers to the receiver -- the value the extension was called on -- and can usually be omitted just like in a regular member function.
Example: Using this Inside an Extension
fun Int.isEven(): Boolean = this % 2 == 0
fun main() {
println("4 is even: ${4.isEven()}")
println("7 is even: ${7.isEven()}")
}
Login to try C/C++/Java/PHP code in the editor
Extensions on Standard Library Types
Extension functions are especially handy for adding convenient behavior to types you cannot modify directly, including standard library or third-party classes.
Example: Extensions on Standard Library Types
fun List<Int>.secondOrNull(): Int? = if (this.size >= 2) this[1] else null
fun main() {
println(listOf(10, 20, 30).secondOrNull())
println(listOf(10).secondOrNull())
}
Login to try C/C++/Java/PHP code in the editor
Static Resolution of Extensions
Which extension function gets called is decided at compile time based on the declared (static) type of the expression, not the object's actual runtime type -- unlike overridden member functions.
Note: This prints "An animal" because animal is statically typed as Animal, even though it holds a Dog at runtime.
Example: Static Resolution of Extensions
open class Animal
class Dog : Animal()
fun Animal.describe() = "An animal"
fun Dog.describe() = "A dog"
fun main() {
val animal: Animal = Dog()
println(animal.describe())
}
Login to try C/C++/Java/PHP code in the editor
- Assuming an extension function actually modifies the original class; it is resolved statically and does not change the class itself in any way.
- Expecting extension functions to be polymorphic like member functions; which extension gets called is determined by the declared type at compile time, not the runtime type.
- Forgetting to import an extension function declared in another package, since it must be imported just like any other top-level function.
- An extension function is declared as
fun ReceiverType.functionName(...) { ... }, adding a callable method to an existing type. - Inside the extension,
thisrefers to the receiver instance the function was called on. - Extension functions are resolved statically based on the declared type, not dynamically based on the actual runtime type.
- Extension functions do not actually modify the original class; they are just syntactic sugar for a top-level function call.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: