In this article, you will learn to extend a class with new functionality using extension functions.
Extension Function
Kotlin provides the ability to add methods to the existing classes without having to inherit from the class or use design patterns such as Decorator to do this.
This is achieved using special declarations called extensions. Using extensions when a function is added to an existing class, it belongs to that class not internally but externally known as Extension Function.
The created extension functions are available for calling in the usual way as if they were methods of the original class.
To declare an extension function, we need to prefix its name with a receiver type, i.e. the type being extended or the class name.
fun <class_name>.<method_name>()
Example
class Person { var skills: String? = null fun show() { println(skills) } } fun main(args: Array<String>) { var p1 = Person() p1.skills = "JAVA" p1.show() var p2 = Person() p2.skills = "KOTLIN" p2.show() //p3 has both skills //calling extension function add() var p3 = p1.add(p2) p3.show() } //definition of extension func add() fun Person.add(person: Person): Person { var p = Person() p.skills = this.skills + " , " + person.skills return p }
Output
JAVA KOTLIN JAVA , KOTLIN
Example explained
- The declare Person.add() function is an extension function, where class name (Person) is known as receiver type.
- The this keyword inside the extension function refers the receiver object (p1).
- The add() function will concatenate the skills(property) of two object of Person type and return an object of Person type (having both skills).
In case we want to define an extension function which has the same name and signature as that of a member function present inside the receiver class, then always the member function will execute when we make a call to the function.
Example
class Example { fun printFunctionType() { println("Class method") } } fun Example.printFunctionType() { println("Extension function") } fun main(args: Array<String>) { //member function always wins Example().printFunctionType() }
Output
Class method
However, it’s perfectly OK for extension functions to overload member functions which have the same name but a different signature.
Example
class Example {
fun printFunctionType() {
println("Class method")
}
}
public fun Example.printFunctionType(i: Int) {
println("Extension function")
}
fun main(args: Array<String>) {
Example().printFunctionType(1)
}
Output
Extension method
Extended library class using extension function
Kotlin not only allows the user-defined classes to be extended but also the library classes can be extended. The extension function can be added to library classes and used in a similar way as for user-defined classes.
The following example demonstrates an extension function created for a built-in class String.
Example
//extending built-in class String fun main(args: Array<String>) { val str1 = "Hello " val str2 = "World" val str3 = "Hey " //calling extension function add() val result = str3.add(str1, str2) println("The new string is: $result") } //definition of extension function add() fun String.add(s1: String, s2: String): String { var newStr = this + s1 + s2 return newStr }
Output
The new string is: Hey Hello World
Example explained
- The declare String.add() function is an extension function, where class name (String) is the receiver type.
- The this keyword inside the extension function refers the receiver object (str3).
- the add() function will concatenate the two string values (passed during call) with the str3 value (receiver object) and return a value of String type.
Nullable Reciever
Extension functions can also be defined with the class type that is nullable. In this case, the nullability of object is checked using this == null inside the body.
Example
class Person { var skills: String? = null fun show() { println(skills) } } fun main(args: Array<String>) { var p1: Person? = Person() p1?.skills = "KOTLIN" p1.output() p1 = null p1.output() } fun Person?.output() { if (this == null) { println("Null") } else this.show() }
Output
KOTLIN Null
Example explained
- The declare Person?.output() function is an extension function, where class name (Person) is the receiver type.
- The this keyword inside the extension function refers the receiver object (p1).
- When p1 is not null, the else condition of output() will execute which will print the skills property.
- When p1 is null, if condition of output() will execute which will print Null.
Companion Object Extensions
A companion object is an object which is declared inside a class and marked with the companion keyword. Companion object is used to call the member function of class directly using the class name (like static in java).
If a class contain companion object, then we can also define extension functions and properties for the companion object.
Just like the calling of regular member function of the companion object, extension function can be called using only the class name as the qualifier.
Example
class MyClass { companion object { // Member function of companion object fun display() { println("Member function of companion object") } } } // Extension function of companion object fun MyClass.Companion.output() { println("Extension function of companion object") } fun main(args: Array<String>) { //calling member function of companion object MyClass.display() //calling extension function of companion object MyClass.output() }
Output
Member function of companion object Extension function of companion object
Example explained
- The declare MyClass.Companion.output() function is an extension function of companion object of MyClass, where class name (MyClass) is the receiver type.
- MyClass.display() will call member function display() of companion object.
- MyClass.output() will call extension function output() of companion object.