Extension functions in Kotlin
Kotlin is one of the most popular alternatives to Java programming language. Kotlin is JVM based programming language, created by IntelliJ IDEA creators Jet Brains, that offers extension functions, functional programming and much more.
Extension functions are nice Kotlin’s feature, that allows adding new functionality to other classes. If you do not want to inherit the other class or do not want to use Decorator design pattern — you could use extension functions to add additional functionality to the class.
A bit of theory
To define an extension function, you need to to prefix extension function’s name with class name. Keyword this in the extension function points to the receiver object:
fun OriginalObject.functionName(parameter: Type, parameter2: Type2, <…>) {
this.variableInOriginalObject = parameter + parameter2
}
An example
Let’s say have a Kotlin’s class that holds list of integers, and we want to return a list of them are even numbers from this list.
Our data class might look something like:
data class NumbersHolder(
val numbers: List<Int>
)
Our function to filter even numbers is as simple as:
object EvenNumberFilter { fun getEvenNumbers(numbers: List<Int>): List<Int> {
return numbers.filter { it % 2 == 0 }
}}
To test that our function works, we will need to add a test for it:
class NumberFilterTest {
@Test
fun `Filter list of even numbers`() {
val randomNumbers = listOf(5, 7, 8, 3, 16)
val numbersHolder = NumbersHolder(randomNumbers) val evenNumbers = EvenNumberFilter.getEvenNumbers(numbersHolder.numbers) assertEquals(2, evenNumbers.size)
assertEquals(8, evenNumbers[0])
assertEquals(16, evenNumbers[1])
}}
It does work, but code is not pretty. It might be nicer, if we could integrate getEvenNumbers function into NumbersHolder class?
Let’s write an extension function!
data class NumbersHolder(
val numbers: List<Int>
)
// Extension function bellowfun NumbersHolder.evenNumbers(): List<Int> {
return this.numbers.filter { it % 2 == 0 }
}
Let’s use it in the test:
@Test
fun `Filter list of even number with extension function`() {
val randomNumbers = listOf(5, 7, 8, 3, 16)
val numbersHolder = NumbersHolder(randomNumbers) val evenNumbers = numbersHolder.evenNumbers() assertEquals(2, evenNumbers.size)
assertEquals(8, evenNumbers[0])
assertEquals(16, evenNumbers[1])
}
Works perfectly!
Modifying other classes
Of course, the same principle could be applied to other classes as well, including the ones coming from JDK or Kotlin — List, Number etc.
For instance, let’s extend Double class and introduce method half() that divides current value by two. The code might be as simple as:
// Declared in file DoubleExtensionFunction.kt
fun Double.half(): Double = this.div(2)
Let’s write a couple of tests, just to make sure that our extension function works:
@ParameterizedTest
@MethodSource("numbers")
internal fun `Test that we can divide a Double by half`(value: Double, expected: Double) {
assertEquals(expected, value.half())
}
companion object {
@JvmStatic
fun numbers() = listOf(
Arguments.of(10, 5),
Arguments.of(0, 0),
Arguments.of(21, 10.5),
Arguments.of(0.5, 0.25)
)
}
Conclusion
Extension functions are a powerful tool in Kotlin developer’s toolkit, that could help develop software faster. They might increase overall readability of the code and simplify development.
I encourage you to try them! For more information, please see an official documentation on Extension functions.