前言
带你深入理解Kotlin扩展函数和java的关系
环境以及工具
Android Studio 3.3
扩展函数(本kt文件中扩展方法)
//-----------------------扩展函数(本类中扩展方法)-------------------------------------
class Test1 {
var name: String = "boyi.chen"
}
//Test1:接收器类型(receiver type)
//this: 接收器对象(receiver object)
fun Test1.temp() {
println("增加扩展函数,打印扩展类的属性name=${this.name}")
}
fun main(args: Array) {
//-----------------------扩展函数(本kt文件)-------------------------------------
Test1().temp()//输出结果-------------------------增加扩展函数-------------------------
}
复制代码
在这个例子中,Test1是接收器类型,Test1()和this是接收器对象,在这个扩展函数中,你可以使用this直接访问你扩展的类型的函数和属性,就像定义在这个类中的方法一样调用。
这个例子如果看不懂,没关系,文末已经给出答案。
扩展函数(其他包下的kt文件)
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) {
//-----------------------扩展函数(其他包下的kt文件)-------------------------------------
val lenth = StringUtils().CustomGetLenth()
println(lenth)//输出结果-------------------------11-------------------------
}
复制代码
范型化的扩展函数
class Test2 {}
//-----------------------范型化的扩展函数-------------------------------------
fun 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) {
Test2().temp(1)//输出结果-------------------------t is Int:1-------------------------
Test2().temp("Boyi-Chen")//输出结果-------------------------t is String:Boyi-Chen-------------------------
}
复制代码
扩展函数不可覆盖(overriding)
//-----------------------扩展函数不可覆盖(overriding)-------------------------------------
open class View {}
class Button : View() {}
fun View.longClick() = println("base view longClicked")
fun Button.longClick() = println("button longClicked")
fun main(args: Array) {
//-----------------------扩展函数不可覆盖(overriding)-------------------------------------
val button: View = Button()
button.longClick()//输出结果-------------------------base view longClicked-------------------------
val button2: Button = Button()
button2.longClick()//输出结果-------------------------button longClicked-------------------------
}
复制代码
问题
1. 看到这里是不是觉得有点奇怪,扩展函数有什么用?java中有类似的么?
我也是带着这个疑问才去找答案的。
由于Kotlin文件在经过Kotlin编译器编译后会生成Java字节码,所以我只要找到对应的字节码文件就可以找到答案了。 我在字节码文件中找到了答案 StringUtils.kt 源代码
package com.boy.learning.kotlinlearningtravel.extensions.utils
class StringUtils {
var name: String = "StringUtils"
}
fun StringUtils.CustomGetLenth(): Int {
return this.name.length
}
复制代码
StringUtilskt.class 字节码文件
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更方便使用,效率更高。
2. 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是接收者实例化对象,文章开头扩展函数就给大家解释了,还是截个图,大家看着方便点。
源码
请关注公众号并在后台回复:kotlin
Kotlin重构系列分享教程
Kotlin环境搭建
Kotlin重构初体验之告别FindViewById
Kotlin基本类型
Kotlin 控制语句 if when for while
Kotlin返回与跳转
Kotlin 类和对象
Kotlin继承
Kotlin接口
Kotlin重构如何兼容原先的ButterKnife、EventBus3.1
当ButterKnife8.8.1碰到AndroidX怎么办
Githup教程开源项目
Python爬虫系列分享教程
Python爬虫之旅之Selenium库的使用
Python爬虫之旅之豆瓣音乐
请关注我(分享日常开发)
参考文章 gad.qq.com/article/det…