帶你深刻理解Kotlin擴展函數和java的關係java
Android Studio 3.3git
//-----------------------擴展函數(本類中擴展方法)-------------------------------------
class Test1 {
var name: String = "boyi.chen"
}
//Test1:接收器類型(receiver type)
//this: 接收器對象(receiver object)
fun Test1.temp() {
println("增長擴展函數,打印擴展類的屬性name=${this.name}")
}
fun main(args: Array<String>) {
//-----------------------擴展函數(本kt文件)-------------------------------------
Test1().temp()//輸出結果-------------------------增長擴展函數-------------------------
}
複製代碼
在這個例子中,Test1是接收器類型,Test1()和this是接收器對象,在這個擴展函數中,你可使用this直接訪問你擴展的類型的函數和屬性,就像定義在這個類中的方法同樣調用。github
這個例子若是看不懂,不要緊,文末已經給出答案。bash
package com.boy.learning.kotlinlearningtravel.extensions.utils
class StringUtils {
var name: String = "StringUtils"
}
fun StringUtils.CustomGetLenth(): Int {
return this.name.length
}
複製代碼
package com.boy.learning.kotlinlearningtravel.extensions
fun main(args: Array<String>) {
//-----------------------擴展函數(其餘包下的kt文件)-------------------------------------
val lenth = StringUtils().CustomGetLenth()
println(lenth)//輸出結果-------------------------11-------------------------
}
複製代碼
class Test2 {}
//-----------------------範型化的擴展函數-------------------------------------
fun <T> Test2.temp(t: T) {
when (t) {
is String -> println("t is String:$t")
is Int -> println("t is Int:$t")
else -> println("既不是String也不是Int")
}
}
fun main(args: Array<String>) {
Test2().temp(1)//輸出結果-------------------------t is Int:1-------------------------
Test2().temp("Boyi-Chen")//輸出結果-------------------------t is String:Boyi-Chen-------------------------
}
複製代碼
//-----------------------擴展函數不可覆蓋(overriding)-------------------------------------
open class View {}
class Button : View() {}
fun View.longClick() = println("base view longClicked")
fun Button.longClick() = println("button longClicked")
fun main(args: Array<String>) {
//-----------------------擴展函數不可覆蓋(overriding)-------------------------------------
val button: View = Button()
button.longClick()//輸出結果-------------------------base view longClicked-------------------------
val button2: Button = Button()
button2.longClick()//輸出結果-------------------------button longClicked-------------------------
}
複製代碼
因爲Kotlin文件在通過Kotlin編譯器編譯後會生成Java字節碼,因此我只要找到對應的字節碼文件就能夠找到答案了。 我在字節碼文件中找到了答案 StringUtils.kt 源代碼app
package com.boy.learning.kotlinlearningtravel.extensions.utils
class StringUtils {
var name: String = "StringUtils"
}
fun StringUtils.CustomGetLenth(): Int {
return this.name.length
}
複製代碼
StringUtilskt.class 字節碼文件jvm
package com.boy.learning.kotlinlearningtravel.extensions.utils;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
@Metadata(mv={1, 1, 13}, bv={1, 0, 3}, k=2, d1={"\000\f\n\000\n\002\020\b\n\002\030\002\n\000\032\n\020\000\032\0020\001*\0020\002��\006\003"}, d2={"CustomGetLenth", "", "Lcom/boy/learning/kotlinlearningtravel/extensions/utils/StringUtils;", "appKt_debug"})
public final class StringUtilsKt
{
public static final int CustomGetLenth(@NotNull StringUtils $receiver)
{
Intrinsics.checkParameterIsNotNull($receiver, "receiver$0");return $receiver.getName().length();
}
}
複製代碼
其實如今能夠看出來了,擴展函數通過kt編譯器編譯後,生成 public static final 的靜態方法,就是java中的xxxUtils工具類。這樣使得Kotlin比java更方便使用,效率更高。函數
java中使用kt定義的擴展函數(不要問我爲何,反正字節碼中聲明的靜態函數就是這樣的,拿起鍵盤就是幹)工具
public class MainTest {
public static void main(String[] args) {
int lenth = StringUtilsKt.CustomGetLenth(new StringUtils());
System.out.println(lenth);//11
}
}
複製代碼
認真看的同窗可能會看到靜態函數須要傳(@NotNull StringUtils $receiver),這裏的receiver是接收者實例化對象,文章開頭擴展函數就給你們解釋了,仍是截個圖,你們看着方便點。ui
請關注公衆號並在後臺回覆:kotlinthis
Kotlin重構如何兼容原先的ButterKnife、EventBus3.1
當ButterKnife8.8.1碰到AndroidX怎麼辦