Kotlin Extension Functions

Kotlin extension functions and properties are similar to member functions/properties but are defined outside of any class. They let you extend the functionality of a class without having to derive a new class or use any kind of design pattern.

This functionality is helpful when you want to modify classes that you don’t have access to, such as platform APIs or third-party classes.

For example, take the following Android toast function:

private fun toast(message: String) {
  Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

To create an extension function so that Context can use this toast function, create a new file called Extensions.kt and add the following:

fun Context.toast(message: String) {
  Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}

Here we have created an extension function by prefixing the new function with the receiver type, in this case Android’s Context class.

Now we are able to call ‘toast’ from any class that extends from Context, such as an Activity or Fragment in Android:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)
      toast("Extension functions are awesome!")
  }
}

If we want to add default values for the extension’s parameters, we can specify them in the constructor:

fun Context.toast(message: String, length: Int = Toast.LENGTH_SHORT) {
  Toast.makeText(this, message, length).show()
}

And use the extension with a default value or with a different one:

toast("Extension functions are awesome!")

toast("Extension functions are awesome!", Toast.LENGTH_LONG)

Just like extension functions, Kotlin also support extension properties:

val List.lastIndex: Int
  get() = size - 1

Extension functions only have access to public properties and functions of the class they are extending. Extension functions do not modify the classes or instances they are extending, but rather make these new functions callable via dot-notation, making their integration with existing classes and objects appear seamless.

Note that extensions are resolved statically:

open class Vehicle

class Truck: Vehicle()

fun Vehicle.getName() = "Vehicle"
fun Truck.getName() = "Truck"

fun printClassName(v: Vehicle) {
  println(v.getName())
}

printClassName(Truck()) // prints Vehicle

The above snippet outputs Vehicle because the extension function getName() is determined by the declared type of the v parameter, which is of the Vehicle class.

It would be very easy to use extensions to implement a variety of abstractions that could make your code a lot harder to understand and maintain, so don’t abuse the power of extension functions. And remember: Static type is resolved at compiled time.

Resources

  • Kotlin Programming Language

    Kotlin

Blockchain in a Business Network