I have seen many interesting topics about Kotlin on portal.kotlin-academy.com/#/ recently. Personally, I think it is very suitable for Kotlin lovers, interested partners can consult by themselves.

The interesting Kotlin series records their understanding of each question.

0 x04: Lambda runnables

fun run(a) {
    val run: () -> Unit = {
        println("Run run run!")}object : Runnable {
        override fun run(a) = run()
    }.run()
}

fun main(args: Array<String>) {
    run()
}
Copy the code

What is the result of the above code? Optional:

  1. “Run run run!”
  2. Doesn’t compile
  3. StackOverflowError
  4. None of the above

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

Analysis of the

Focus on the

fun run(a) {
    val run: () -> Unit = {
        println("Run run run!")}object : Runnable {
        override fun run(a) = run()
    }.run()
}
Copy the code

The outermost layers, run() and main(), are one hierarchy and are both in-file functions, which are static functions. A variable is defined in run()

val run: () -> Unit = {
    println("Run run run!")}Copy the code

The run variable is a function type variable of type () -> Unit. An anonymous object is also defined

object : Runnable {
    override fun run(a) = run()
}.run()
Copy the code

Define an anonymous object that implements the Runnable interface and call its run() method. The implementation of the run() method in the Runnable interface is the run function type variable that precedes the call.

Comb through each part of the topicrunThe problem will be solved.

So, starting with main, the entry to function execution, the order of execution is as follows:

Graph LR main function --> static function run --> anonymous object run --> function type run

So eventually the function type variable run will be called and executed

 println("Run run run!")
Copy the code

Therefore, the correct answer is:

Option 1. Run Run Run!

The anonymous object in the problem could be Lambda shorthand, which would make it even more confusing to see run all over the screen.

fun run(a) {
    val run: () -> Unit = {
        println("Run run run!")
    }

    Runnable { run() }.run()
}

fun main(args: Array<String>) {
    run()
}
Copy the code

extension

Adjust the code in the problem

fun run(a) {

    val run: () -> Unit = {
        println("Run run run!")}// Add a new run function
    fun run(a) = println("Hello World")

    object : Runnable {
        override fun run(a) = run()
    }.run()
}

fun main(args: Array<String>) {
    run()
}
Copy the code

What does the program run console output at this point?

Answer: Hello World.

There is a call priority issue involved.

Here’s a question on StackOverflow about this:

Stackoverflow.com/questions/5…

There’s also a Github post that goes into detail:

Github.com/JetBrains/k…

Interested friends can consult by themselves.

If you want the program to say Run Run Run! , some adjustments are needed:

fun run(a) {
    val run: () -> Unit = {
        println("Run run run!")}fun run(a) = println("Hello World")

    object : Runnable {
        override fun run(a) = (run)()
    }.run()
}

fun main(args: Array<String>) {
    run()
}
Copy the code

or

fun run(a) {
    val run: () -> Unit = {
        println("Run run run!")}fun run(a) = println("Hello World")

    object : Runnable {
        override fun run(a) = run.invoke()
    }.run()
}

fun main(args: Array<String>) {
    run()
}
Copy the code

conclusion

  1. Anonymous objects can call functions and variables in their scope.
  2. There are two ways to call a function type variable:(a)invoke().
  3. SAM conversion Lambda