Fungsi tingkat tinggi sangat membantu dan benar-benar dapat meningkatkan reusability
kode. Namun, salah satu kekhawatiran terbesar tentang penggunaannya adalah efisiensi. Ekspresi Lambda dikompilasi ke kelas (seringkali kelas anonim), dan pembuatan objek di Java adalah operasi yang berat. Kita masih dapat menggunakan fungsi tingkat tinggi dengan cara yang efektif, sambil menjaga semua manfaat, dengan membuat fungsi sebaris.
inilah fungsi inline ke dalam gambar
Ketika suatu fungsi ditandai sebagai inline
, selama kompilasi kode, kompilator akan mengganti semua panggilan fungsi dengan badan fungsi yang sebenarnya. Selain itu, ekspresi lambda yang diberikan sebagai argumen diganti dengan tubuh aslinya. Mereka tidak akan diperlakukan sebagai fungsi, tetapi sebagai kode aktual.
Singkatnya: - Inline -> daripada dipanggil, mereka digantikan oleh kode badan fungsi pada waktu kompilasi ...
Di Kotlin, menggunakan fungsi sebagai parameter fungsi lain (disebut fungsi tingkat tinggi) terasa lebih alami daripada di Java.
Namun, penggunaan lambda memiliki beberapa kelemahan. Karena mereka adalah kelas anonim (dan karenanya, objek), mereka memerlukan memori (dan bahkan mungkin menambah jumlah metode keseluruhan aplikasi Anda). Untuk menghindari hal ini, kita dapat menggunakan metode kita sebaris.
fun notInlined(getString: () -> String?) = println(getString())
inline fun inlined(getString: () -> String?) = println(getString())
Dari contoh di atas : - Kedua fungsi ini melakukan hal yang persis sama - mencetak hasil dari fungsi getString. Yang satu sejajar dan yang lainnya tidak.
Jika Anda memeriksa kode java yang telah didekompilasi, Anda akan melihat bahwa metodenya benar-benar identik. Itu karena kata kunci inline adalah instruksi kepada kompilator untuk menyalin kode ke dalam situs panggilan.
Namun, jika kita meneruskan tipe fungsi apa pun ke fungsi lain seperti di bawah ini:
//Compile time error… Illegal usage of inline function type ftOne...
inline fun Int.doSomething(y: Int, ftOne: Int.(Int) -> Int, ftTwo: (Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/
}
Untuk mengatasinya, kita bisa menulis ulang fungsi kita seperti di bawah ini:
inline fun Int.doSomething(y: Int, noinline ftOne: Int.(Int) -> Int, ftTwo: (Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/}
Misalkan kita memiliki fungsi urutan yang lebih tinggi seperti di bawah ini:
inline fun Int.doSomething(y: Int, noinline ftOne: Int.(Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/}
Di sini, kompilator akan memberi tahu kita untuk tidak menggunakan kata kunci inline ketika hanya ada satu parameter lambda dan kita meneruskannya ke fungsi lain. Jadi, kita bisa menulis ulang fungsi di atas seperti di bawah ini:
fun Int.doSomething(y: Int, ftOne: Int.(Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/
}
Catatan : -kami harus menghapus kata kunci noinline juga karena hanya dapat digunakan untuk fungsi inline!
Misalkan kita memiliki fungsi seperti ini ->
fun intercept() {
// ...
val start = SystemClock.elapsedRealtime()
val result = doSomethingWeWantToMeasure()
val duration = SystemClock.elapsedRealtime() - start
log(duration)
// ...}
Ini berfungsi dengan baik tetapi inti logika fungsi tersebut tercemar dengan kode pengukuran sehingga mempersulit kolega Anda untuk mengerjakan apa yang terjadi. :)
Inilah bagaimana fungsi sebaris dapat membantu kode ini:
fun intercept() {
// ...
val result = measure { doSomethingWeWantToMeasure() }
// ...
}
inline fun <T> measure(action: () -> T) {
val start = SystemClock.elapsedRealtime()
val result = action()
val duration = SystemClock.elapsedRealtime() - start
log(duration)
return result
}
Sekarang saya dapat berkonsentrasi untuk membaca apa maksud utama fungsi intercept () tanpa melewatkan baris kode pengukuran. Kami juga mendapat manfaat dari opsi untuk menggunakan kembali kode itu di tempat lain yang kami inginkan
inline memungkinkan Anda memanggil fungsi dengan argumen lambda dalam closure ({...}) daripada meneruskan lambda like measure (myLamda)