SyntaxStudy
Sign Up
Kotlin Beginner 1 min read

Extension Functions

Extension functions let you add new functions to existing classes without modifying their source code or using inheritance. You declare an extension by prefixing the function name with the type you are extending (the receiver type). Inside the function body, this refers to the receiver instance. Extension functions are resolved statically at compile time based on the declared type of the variable, not the runtime type. They do not actually modify the class; the compiler generates a static helper function that takes the receiver as its first parameter. Extension functions are especially powerful when extending platform types like String, List, or Int, and they are the mechanism behind Kotlin's standard library scope functions and collection utilities.
Example
// Extension on String
fun String.isPalindrome(): Boolean {
    val cleaned = this.lowercase().filter { it.isLetter() }
    return cleaned == cleaned.reversed()
}

fun String.wordCount(): Int = this.trim().split("\\s+".toRegex()).size

// Extension on Int
fun Int.factorial(): Long {
    require(this >= 0) { "Factorial undefined for negative numbers" }
    return if (this <= 1) 1L else this * (this - 1).factorial()
}

// Extension on a list
fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null

// Extension on nullable type
fun String?.orEmpty2(): String = this ?: ""

// Extension with generic receiver
fun <T : Comparable<T>> T.clamp(min: T, max: T): T = when {
    this < min -> min
    this > max -> max
    else       -> this
}

fun main() {
    println("racecar".isPalindrome())   // true
    println("Hello World".isPalindrome())  // false
    println("The quick brown fox".wordCount())  // 4

    println(5.factorial())   // 120
    println(0.factorial())   // 1

    println(listOf(10, 20, 30).secondOrNull())   // 20
    println(emptyList<Int>().secondOrNull())       // null

    val name: String? = null
    println(name.orEmpty2())   // ""

    println(15.clamp(0, 10))    // 10
    println(-5.clamp(0, 100))   // 0
    println(50.clamp(0, 100))   // 50
}