How Extensions Are Resolved

Static Resolution

Extensions do not really modify the class. The compiler turns them into normal static functions that take the receiver as the first parameter. Two consequences:

  • Which extension is called depends on the declared type of the variable, not the runtime type (no polymorphism).
  • If the class already has a member with the same signature, the member always wins.
  • Extensions cannot access private members of the receiver.

Example

open class Animal
class Dog : Animal()

fun Animal.sound() = "generic sound"
fun Dog.sound() = "woof"

class Robot { fun beep() = "member beep" }
fun Robot.beep() = "extension beep"   // shadowed: never called

fun main() {
    val a: Animal = Dog()
    println(a.sound())        // declared type is Animal
    println(Dog().sound())
    println(Robot().beep())
}

Output

generic sound
woof
member beep

Scope and Imports

Top-level extensions are visible in their package; elsewhere import them like any function: import com.shop.utils.toRupees. Keep them in files such as StringExt.kt or ViewExt.kt.