Search code examples
kotlinkotlin-extension

Kotlin: When extension function hides the class default implementation?


I'm trying to figure out when overriding an existing class function, with an extension function of the same signature - will take effect?

Here is my sample code:

fun String.toUpperCase(): String = "ext. function impl."

fun main(args: Array<String>) {

    println("Hello".toUpperCase()) // ext. function impl.

    println(MyClass().toUpperCase()) // class impl.

}

class MyClass {
    fun toUpperCase() : String {
        return "class impl."
    }
}

fun MyClass.toUpperCase() : String {
    return "ext. function impl."
}

So:

  • What are the rules? when each will be called?
  • How can I override this decision? is it possible?

Solution

  • From the Kotlin docs (emphasis not mine):

    If a class has a member function, and an extension function is defined which has the same receiver type, the same name and is applicable to given arguments, the member always wins.

    The reason your string example works is because the library-provided String.toUpperCase() is already an extension function, not a member function. The docs don't state what happens here, but seems reasonable to assume that a local extension wins.


    I don't imagine there's any way to alter this behaviour. And that's probably for the best, as it would violate the principle of least astonishment in many cases (i.e. behaviour that's difficult to understand).