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 C
class 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:
- Doesn’t Compile
- Rutime error
- “c”
- “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.