Kotlin extension function

Kotlin gives the programmer the ability to add more functionality to the existing classes, by without inheriting them. This is achieved through a feature known as extensions. When a function is added to an existing class it is known as Extension Function.

To add an extension function to a class, define a new function appended to the classname as shown in the following example:

filter_none

edit
close

play_arrow

link
brightness_4
code

package kotlin1.com.programmingKotlin.chapter1
  
// A sample class to demonstrate extension functions
class Circle (val radius: Double){
    // member function of class
    fun area(): Double{
        return Math.PI * radius * radius;
    }
}
fun main(){
    // Extension function created for a class Circle
    fun Circle.perimeter(): Double{
        return 2*Math.PI*radius;
    }
    // create object for class Circle
    val newCircle = Circle(2.5);
    // invoke member function
    println("Area of the circle is ${newCircle.area()}")
    //invoke extension function
    println("Perimeter of the circle is ${newCircle.perimeter()}")
}

chevron_right


Output:



Area of the circle is 19.634954084936208
Perimeter of the circle is 15.707963267948966

Explanation:
Here, a new function is appended to class using dot notation with class Circle.perimeter() and its return type is Double. In the main function an object is created to instantiate the class Circle and invoked the function in println() statement. When the member function is invoked it returns the area of circle and similarly extension function returns the perimeter of circle.

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 user-defined class-

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(){
  
    // Extension function defined for Int type
    fun Int.abs() : Int{
        return if(this < 0) -this else this
    }
  
    println((-4).abs())
    println(4.abs())
}

chevron_right


Output:

4
4

Explanation: Here, we have extended the library function using an extension function. We performed the modulus operation on an Integer value. We have passed the integer value -4 and 4 and obtain positive value for both. If parameter value is less than 0 than returns -(value) and if parameter value is greater than zero returns the same value.

Extensions are resolved statically –

One important point to note about the extension functions is that they are resolved statically i.e which extension function is executed depends totally on the type of the expression on which it is invoked, rather than on the type resolved on the final execution of the expression at runtime.

The following example will make the above argument clear:

filter_none

edit
close

play_arrow

link
brightness_4
code

// Open class created to be inherited
open class A(val a:Int, val b:Int){
}
  
// Class B inherits A
class B():A(5, 5){}
  
fun main(){
      
    // Extension function operate defined for A
    fun A.operate():Int{
        return a+b
    }
  
    // Extension function operate defined for B
    fun B.operate():Int{
        return a*b;
    }
  
    // Function to display static dispatch
    fun display(a: A){
        print(a.operate())
    }
  
    // Calling display function 
    display(B())
}

chevron_right


Output:

10

Explanation:
If you are familiar with Java or any other object-oriented programming language, you might notice in the above program, that since class B inherits class A and the argument passed display function is an instance of class B. The output should be 25 according to the concept of the dynamic method dispatch, but since the extension functions are statically resolved, so the operate function is called on type A. Hence the output is 10.

Nullable Reciever –

Extension functions can also be defined with the class type that is nullable. In this case, when the check for null is added inside the extension function and the appropriate value is returned.


Example of an extension function as a nullable receiver –

filter_none

edit
close

play_arrow

link
brightness_4
code

// A sample class to display name name
class AB(val name: String){
    override fun toString(): String {
        return "Name is $name"
    }
}
  
fun main(){
    // An extension function as a nullable receiver
    fun AB?.output(){
        if(this == null){
            println("Null")
        }else{
            println(this.toString())
        }
    }
  
    val x = AB("Charchit")
      
    // Extension function called using an instance
    x.output()
    // Extension function called on null
    null.output()
}

chevron_right


Output:

Name is Charchit
Null

Companion Object Extensions –

If a class contain companion object, then we can also define extension functions and properties for the companion object.

Companion object declaration –

filter_none

edit
close

play_arrow

link
brightness_4
code

class MyClass {
    // companion object declaration
    companion object {
        fun display(){
            println("Function declared in companion object")
        }
    }
}
fun main(args: Array<String>) {
   // invoking member function 
   val ob = MyClass.display()  
}

chevron_right


Output:

Function declared in 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.
Companion object extension example –

filter_none

edit
close

play_arrow

link
brightness_4
code

class MyClass {
    companion object {
        // member function of companion object
        fun display(str :String) : String{
            return str
        }
    }
    // extension function of companion object
fun MyClass.Companion.abc(){
    println("Extension function of companion object")
}
fun main(args: Array<String>) {
    val ob = MyClass.display("Function declared in companion object")
    println(ob)
    // invoking the extension function 
    val ob2 = MyClass.abc()
}

chevron_right


Output:

Function declared in companion object
Extension function of companion object


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.