Skip to main content
Kotlin Basics
CHAPTER 18 Beginner

Extension Functions and Higher-Order Functions

Updated: May 18, 2026
5 min read

# CHAPTER 18

Extension Functions and Higher-Order Functions

1. Chapter Introduction

Kotlin was designed not just as an Object-Oriented language, but also as a Functional language. This means functions are treated as "first-class citizens"—you can pass them as parameters, return them from other functions, and assign them to variables! Furthermore, Kotlin introduces Extension Functions, a feature that allows you to add brand new methods to classes you don't even own (like the standard String class).

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Write and use Extension Functions.
  • Understand the concept of "Receiver types".
  • Understand what a Higher-Order Function is.
  • Pass a function as an argument to another function.
  • Define Function Types (e.g., (Int, Int) -> Int).

3. Extension Functions

Have you ever used a library class (like Kotlin's String) and wished it had a specific method, like .removeFirstAndLast()? In Java, you'd have to create a messy StringUtils helper class. In Kotlin, you can literally "extend" the String class yourself!
kotlin
123456789101112
// We add a new function to the String class!
// 'String' is the receiver type. 'this' refers to the actual string.
fun String.removeFirstAndLast(): String {
    return this.substring(1, this.length - 1)
}

fun main() {
    val myWord = "Kotlin"
    
    // It looks like a native Kotlin method!
    println(myWord.removeFirstAndLast()) // Output: otli
}

*Note: Extension functions do not actually modify the original class source code. The compiler resolves them statically. They are syntactic sugar that makes code highly readable.*

4. Higher-Order Functions

A Higher-Order Function is a function that does at least one of two things:
  1. 1. Takes another function as a parameter.
  1. 2. Returns a function.

#### Defining a Function Type If we want to pass a function as a parameter, we must declare its type.

  • () -> Unit : A function taking no arguments and returning nothing.
  • (Int, Int) -> Int : A function taking two Ints and returning an Int.

#### Passing a Function as a Parameter Let's build a calculator that accepts the math operation as a function!

kotlin
123456789101112131415
// The 3rd parameter 'operation' is a FUNCTION!
fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
    return operation(x, y) // We execute the passed function here
}

// A standard function that matches the (Int, Int) -> Int signature
fun sum(a: Int, b: Int): Int {
    return a + b
}

fun main() {
    // We pass the 'sum' function using the :: operator
    val result = calculate(10, 5, ::sum)
    println("Result: $result") // 15
}

5. Passing Anonymous Functions (Lambdas Preview)

Passing functions using ::sum is okay, but Kotlin allows us to define the function *inline* exactly when we need it. These are called Lambdas (which we will cover fully in Chapter 19).
kotlin
12345
fun main() {
    // We define the logic { a, b -> a * b } right inside the call!
    val result = calculate(10, 5, { a, b -> a * b })
    println("Multiplied: $result") // 50
}

6. Built-in Higher-Order Functions

You have likely used Higher-Order Functions already without realizing it! The .filter and .map methods on Collections take a function as a parameter to know *how* to filter the data.

7. Common Mistakes

  • Abusing Extension Functions: Because they are so easy to write, beginners often write Extension Functions for everything instead of creating proper Classes. If an extension relies on state, it should probably be a method inside a Class.
  • Forgetting ::: If you want to pass an existing function into a higher-order function, you must use the method reference operator :: (e.g., ::sum). Writing calculate(5, 5, sum) will cause an error because it thinks you are trying to *execute* sum rather than pass it.

8. Best Practices

  • Extend 3rd-Party Libraries: Extension functions shine when you are using external libraries (like Android UI elements or JSON parsers) and want to create shortcut methods for repetitive tasks specific to your project.

9. Exercises

  1. 1. Write an extension function for Int called .isEven(). It should return a Boolean.
  1. 2. Inside .isEven(), check if this % 2 == 0.
  1. 3. In main(), print 10.isEven() and 7.isEven().

10. MCQs with Answers

Question 1

What feature allows you to add new methods to existing classes without modifying their source code?

Question 2

In fun String.makeHappy(): String, what is String called?

Question 3

Inside an Extension Function, what keyword refers to the object instance the function was called on?

Q4. Do Extension Functions actually modify the original compiled class (e.g., adding a method to Java's String class natively)? a) Yes b) No, they are resolved statically by the compiler as syntactic sugar Answer: b) No, they are resolved statically.
Question 5

What makes a function a "Higher-Order Function"?

Question 6

What does the function type (Int, Int) -> Boolean describe?

Question 7

If you have a function fun greet(), how do you pass it as an argument to another function?

Question 8

What does () -> Unit mean?

Q9. Are functions treated as "First-Class Citizens" in Kotlin? a) Yes, they can be assigned to variables and passed around b) No, only Objects can Answer: a) Yes.

Q10. Can you define an extension function on an external library class you did not write? a) Yes b) No Answer: a) Yes.

11. Interview Questions

  • Q: What is an Extension Function? Does it violate Object-Oriented Encapsulation? (Answer: No, because extension functions cannot access private members of the receiver class. They only have access to the public API).
  • Q: Explain what a Higher-Order Function is and provide an example of a common one found in the Kotlin standard library (e.g., .map() or .filter()).

12. Summary

Kotlin bridges the gap between Object-Oriented and Functional programming. Extension functions allow developers to clean up their codebase by adding intuitive helper methods directly to relevant types. Higher-Order Functions unlock immense flexibility, allowing behaviors (functions) to be injected dynamically into code at runtime.

13. Next Chapter Recommendation

Passing ::sum is useful, but declaring an entire function just to use it once is tedious. In Chapter 19: Lambdas and Functional Programming, we will learn how to write anonymous functions (Lambdas) directly in the parameters, unlocking the true power of collections manipulation.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·