In Kotlin, functions are treated as first-class citizens, which means you can declare function types, create lambda expressions, and pass functions as parameters to other functions. Here’s a guide on how to design function types and pass them as parameters:
1. Function Types
A function type in Kotlin is defined by the types of its parameters and its return type. The syntax is:
(A, B) -> C
This represents a function that takes two parameters of types A
and B
and returns a value of type C
.
For example:
(String, Int) -> Boolean
This represents a function that takes a String
and an Int
as parameters and returns a Boolean
.
2. Passing Functions as Parameters
Here’s how you can pass functions as parameters in Kotlin:
Step 1: Define a Function Type as a Parameter
You can define a parameter of a function as a function type. For example:
fun operateOnNumber(x: Int, operation: (Int) -> Int): Int {
return operation(x)
}
In this example:
x
is anInt
.operation
is a function that takes anInt
as a parameter and returns anInt
.
Step 2: Pass a Lambda Expression
You can call this function and pass a lambda expression as the operation
parameter:
fun main() {
val result = operateOnNumber(5) { it * 2 }
println(result) // Output: 10
}
Step 3: Pass Another Function
You can also define a named function and pass it as an argument:
fun double(x: Int): Int {
return x * 2
}
fun main() {
val result = operateOnNumber(5, ::double)
println(result) // Output: 10
}
Here, ::double
is a function reference to the double
function.
3. Storing Functions in Variables
You can store lambda expressions or function references in variables:
val add: (Int, Int) -> Int = { a, b -> a + b }
val subtract: (Int, Int) -> Int = { a, b -> a - b }
fun main() {
println(add(5, 3)) // Output: 8
println(subtract(5, 3)) // Output: 2
}
4. Using Higher-Order Functions
A higher-order function is a function that takes other functions as parameters or returns functions.
Example:
fun performOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun main() {
val sum = performOperation(5, 3) { x, y -> x + y }
println(sum) // Output: 8
}
5. Nullable Function Types
If you want to allow null values for a function type, you can add a ?
. For example:
fun callFunctionIfNotNull(func: ((Int) -> Int)?) {
func?.invoke(10)
}
fun main() {
callFunctionIfNotNull { it * 2 } // Output: 20
callFunctionIfNotNull(null) // No output
}
6. Returning a Function
You can also design functions that return other functions:
fun getOperation(type: String): (Int, Int) -> Int {
return when (type) {
"add" -> { a, b -> a + b }
"subtract" -> { a, b -> a - b }
else -> { _, _ -> 0 }
}
}
fun main() {
val operation = getOperation("add")
println(operation(10, 5)) // Output: 15
}
Summary
- Define function types using
(parameterType1, parameterType2, ...) -> returnType
. - Pass functions using lambda expressions
{...}
or function references::functionName
. - Use nullable function types if necessary.
- Create functions that return other functions for more flexible and dynamic programming.