Kotlin. Referensi Lambda vs Fungsi

Kotlin telah lama menjadi bahasa pemrograman utama di Android. Salah satu alasan mengapa saya menyukai bahasa ini adalah karena fungsi di dalamnya adalah objek kelas satu . Artinya, suatu fungsi dapat dilewatkan sebagai parameter, digunakan sebagai nilai kembali, dan ditetapkan ke variabel. Selain itu, alih-alih fungsi, Anda bisa meneruskan apa yang disebut lambda . Dan baru-baru ini saya punya masalah menarik terkait mengganti lambda dengan referensi fungsi.





Bayangkan kita memiliki kelas Button



yang menerima fungsi dalam konstruktor sebagai parameteronClick







class Button(
    private val onClick: () -> Unit
) {
    fun performClick() = onClick()
}
      
      



Dan ada kelas ButtonClickListener



yang mengimplementasikan logika klik tombol





class ButtonClickListener {
    fun onClick() {
        print(" ")
    }
}
      
      



Di kelas ScreenView



, kami menyimpan variabel lateinit var listener: ButtonClickListener



dan membuat tombol, yang diteruskan lambda, di dalamnya metode ini dipanggilButtonClickListener.onClick







class ScreenView {
    lateinit var listener: ButtonClickListener
    val button = Button { listener.onClick() }
}
      
      



Dalam metode ini, main



kami membuat objek ScreenView



, menginisialisasi variabel listener



dan mensimulasikan mengklik tombol





fun main() {
    val screenView = ScreenView()
    screenView.listener = ButtonClickListener()
    screenView.button.performClick()
}
      
      



Setelah memulai aplikasi, semuanya bekerja dengan baik dan baris "Tombol ditekan" ditampilkan.





Sekarang mari kembali ke kelas ScreenView



dan lihat baris tempat tombol dibuat - val button = Button { listener.onClick() }



. Anda mungkin telah memperhatikan bahwa metode ButtonClickListener.onClick



ini memiliki tanda tangan yang mirip dengan fungsi onClick: () -> Unit



yang diambil oleh konstruktor tombol kita, yang berarti bahwa kita dapat mengganti ekspresi lambda dengan referensi fungsi. Hasilnya, kita dapatkan





class ScreenView {
    lateinit var listener: ButtonClickListener
    val button = Button(listener::onClick)
}
      
      



- listener





Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property listener has not been initialized
at lambdas.ScreenView.<init>(ScreenView.kt:6)
at lambdas.ScreenViewKt.main(ScreenView.kt:10)
at lambdas.ScreenViewKt.main(ScreenView.kt)
      
      



, Java . .





Function0



invoke



, . - listener.onClick()







private final Button button = new Button((Function0)(new Function0() {
    public final void invoke() {
       ScreenView.this.getListener().onClick();
    }
}));
      
      



, listener



.





. Function0



, invoke()



, , onClick



this.receiver



. receiver



Function0



listener



, listener



lateinit



, receiver



- listener



null



, . .





Button var10001 = new Button;
Function0 var10003 = new Function0() {
   public final void invoke() {
      ((ButtonClickListener)this.receiver).onClick();
   }
};
ButtonClickListener var10005 = this.listener;
if (var10005 == null) {
   Intrinsics.throwUninitializedPropertyAccessException("listener");
}

var10003.<init>(var10005);
var10001.<init>((Function0)var10003);
this.button = var10001;
      
      



, , , , , , .





Ini mengarah pada masalah menarik berikut: Apa yang akan dicetak setelah program dimulai?





class Button(
    private val onClick: () -> Unit
) {
    fun performClick() = onClick()
}

class ButtonClickListener(
    private val name: String
) {
    fun onClick() {
        print(name)
    }
}

class ScreenView {
    var listener = ButtonClickListener("First")
    val buttonLambda = Button { listener.onClick() }
    val buttonReference = Button(listener::onClick)
}

fun main() {
    val screenView = ScreenView()
    screenView.listener = ButtonClickListener("Second")
    screenView.buttonLambda.performClick()
    screenView.buttonReference.performClick()
}
      
      



  1. FirstFirst







  2. FirstSecond







  3. SecondFirst







  4. SecondSecond







Menjawab

3





Terima kasih telah membaca, semoga ada yang tertarik dan bermanfaat!








All Articles