Recently I have seen a lot of interesting topics about Kotlin on portal.kotlin-academy.com/#/. Personally, I think it is very suitable for Kotlin lovers. Interested partners can consult it by themselves.

The interesting Kotlin series notes your understanding of each question.

0x09: Extensions are resolved statically

open class Cclass D: C(a)fun C.foo(a) = "c"fun D.foo(a) = "d"fun printFoo(c: C) {
    println(c.foo())
}
​
fun main(args: Array<String>) {
    printFoo(D())
}
Copy the code

What is the result of running the above code? Optional:

  1. Doesn’t Compile
  2. Rutime error
  3. “c”
  4. “d”

Think about it and write down the answers in your mind.

Analysis of the

Basic situation

  • Class C is the parent of class D, and each has an extension function named foo. An extension function of class C returns the string “C”, and an extension function of class D returns the string “D”;

  • We define a top-level function printFoo() that takes type C;

  • PrintFoo is called inside main, passing in an instance of D.

inertia

In main(), printFoo() is passed as a D object, and d. foo() is called.

Is this analysis correct?

This analysis would be fine if Kotlin extension functions were essentially member functions, but are extension functions essentially member functions?

What is the nature of the Kotlin extension function?

When things are unclear, for example

Define an extension function with receiver as String.

fun String.suffix(suffix: String) = this + suffix
Copy the code

Unidentified decompile

  • The bytecode

  • Decompile Java code

  • The Kotlin extension function is used in Java
Public class Test {public static void main(String[] args) {String result = Extensions_are_resolved_staticallyKt.suffix("Hello", " OpenCV or Android"); System.out.println(result); }}Copy the code

To sum up, Kotlin extension functions are static functions in nature, and receiver is the first parameter of the corresponding static function in the bytecode. So when you call the extension function defined by Kotlin in Java, you need to pass in receiver as the first parameter.

The problem solving

Back to the topic

fun printFoo(c: C) {
    println(c.foo())
}
Copy the code

Since the argument type is C, the code for c.foo() corresponds to the static function compiled by fun C.foo() = “C”. Although D() is passed in at runtime, it is forced into C and executes the static method corresponding to fun C.foo() = “C”. The correct answer is:

Option 3: “C”

extension

Let’s add a member function foo() to class C and class D, respectively.

Package puzzlers class C {open fun foo() = "cc" // class C member function foo} class D: C() {override fun foo() = "dd"} fun c.foo () = "C" fun d.foo () = "D" fun printFoo(C: C) { println(c.foo()) } fun main(args: Array<String>) { printFoo(D()) }Copy the code

What should the result be? Tips: Member always win.