Extensions

Extensions is the ability to add new functionality to a class without inheritance. It allows you to write new functions for a class from a third-party library that you can't modify.

Actually this feature is implemented using static methods of the class. Thus, extensions are determined by the type of the expression for which they are called, not by the type of the result of evaluating that expression at runtime, as with virtual methods.

The this keyword inside an extension function refers to the receiver object.

Extensions can be defined with a nullable receiver type.

Extensions can be defined for the companion object of class.

You can declare extension as property of class. But such a property cannot be initialized.

Extensions have the same scoping rules as regular functions.

// fun ClsName.ext_method(...){...}

// Add methods for mutable list of integers
fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2]
    this[index2] = tmp
}

// using
val list = mutableListOf(1, 2, 3)
list.swap(0, 2) 
// nullable receiver type fun Any?.toString(): String { if (this == null) return "null" // after the null check, 'this' is autocast to a non-null type, // so the toString() below // resolves to the member function of the Any class return toString() }
fun MyClass.Companion.printCompanion() { println("companion") } fun main() { MyClass.printCompanion() }
val <T> List<T>.lastIndex: Int get() = size - 1