6

Kotlin. Lambda vs Method Reference

 3 years ago
source link: https://proandroiddev.com/kotlin-lambda-vs-method-reference-fdbd175f6845
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Kotlin. Lambda vs Method Reference

1*cQuNiDIiL_OHhB3Rd0mEyQ.jpeg?q=20
kotlin-lambda-vs-method-reference-fdbd175f6845
Photo by Fotis Fotopoulos from Unsplash is used

Kotlin has been main Android programming language for a while now. One of the reasons I like this language is because functions are first-class citizen. That means a function can be passed as an argument, used as a return value and assigned to a variable. Also, so called lambda can be passed instead of a function. And recently I’ve had an interesting problem related to replacing lambda with a method reference.

Say we have Button class which takes the onClick function as a constructor argument

And we have ButtonClickListener class that implements the logic of button clicks

In the ScreenView class we have lateinit var listener: ButtonClickListener variable. Then we create button in that class and pass lambda to button constructor. In this lambda we call ButtonClickListener.onClick function

We create ScreenView object in main function, initialize listener variable there and perform button click

In this case, after running the program, everything works correctly and “Button clicked” string is printed.

And now let’s go back to ScreenView class and take a look at the line where our button val button = Button { listener.onClick() } is created. You could have noticed that ButtonClickListener.onClick function has the same signature as onClick: () -> Unit function, which is taken by button constructor. Which means lambda can be replaced by method reference. And we’ll get the following

But after running the program, it crashes with the following error: listener field isn’t initialized.

To understand what the problem is, let’s look at the differences of decompiled Java code in both scenarios. I’ll skip details and show the main differences.

When we use lambda the Function0 anonymous class is created and the code from our lambda is called into invoke function. In our case that code is listener.onClick()

That is, if we pass lambda to button constructor, the listener variable will be used after performing button click and it will already be initialized.

And here is what will happen if we use method reference instead of lambda. In this case Function0 anonymous class is created as well but if we have a look at invoke function we’ll see that onClick is called on the this.receiver variable. The receiver field belongs to Function0 class and should be initialized using listener variable, but since listener is lateinit, it is checked against null before initializing receiver. So, because listener isn’t initialized yet, the program crashes

To sum up, the difference between lambda and method reference is that when we use method reference, the instance of variable, the method of which we use, is fixed at the moment the reference is created, not when it is called, unlike what happens when lambda is used.

Hence, an interesting task: What will be printed after the following program runs?

  1. FirstFirst
  2. FirstSecond
  3. SecondFirst
  4. SecondSecond

Look for the answer in the comment section.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK