Kotlin原理-拓展函数

作者: 嘉伟咯 | 来源:发表于2022-01-25 21:19 被阅读0次

原理

拓展函数是kotlin里一个比较常用的特性,例如我们可以给Context拓展一个toast方法:

// MainActivity.kt
fun Context.toast(msg: String) {
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}

private fun foo(context: Context) {
    context.toast("hello world")
}

它的原理其实很简单,就是生成了一个toast方法。拓展函数的this指针实际上是这个生成方法的第一个参数:

/* compiled from: MainActivity.kt */
public final class MainActivityKt {

    public static final void toast(Context $this$toast, String msg) {
        //参数判空
        ...

        // 拓展函数代码
        Toast.makeText($this$toast, msg, 0).show();
    }
}

所以这个this指针实际上是由函数调用的地方传入的对象引用:

private final void foo(Context context) {
    MainActivityKt.toast(context, "hello world");
}

限制

知道了拓展函数的实现原理之后我们就能从原理去理解拓展函数的种种限制.

不能访问私有成员

由于编译成java之后,生成的拓展方法实际是靠第一个参数出入对象引用,然后使用这个对象引用去调用对象的方法。因此我们并没有权限在拓展函数里面调用私有方法:

class TestClass {
    fun publicFun() {}
    private fun privateFun() {}
}

fun TestClass.extFun() {
    publicFun() // 正确,可以调用公有方法

    privateFun() // 错误,不能调用私有方法
}

拓展函数不能实现多态

由于拓展函数并不是真的给类增加一个成员函数,所以父类和子类的同名拓展函数并没有多态的特性。

例如我们为父类和子类拓展同一个foo()函数:

open class Parent
class Child : Parent()

fun Parent.foo() {
    println("parent")
}

fun Child.foo() {
    println("child")
}

然后只要将子类转换成父类,调用的拓展函数就是父类的拓展函数:

val child = Child()
child.foo()
(child as Parent).foo()

// 输出:
// child
// parent

成员函数优先级高,拓展函数不能实现重写

当拓展函数与类本身或者父类的成员函数相同,在实际调用的时候会优先调用成员函数,并不会出现类似重写的效果.

例如我们为一个类编写了一个与成员函数相同的拓展函数,实际优先调用类成员函数:

open class Parent {
    fun foo() {
        println("foo")
    }
}

fun Parent.foo() {
    println("parent")
}

Parent().foo()

// 输出:
// foo

就算是为子类编写了一个与父类成员函数相同的拓展函数,也会优先调用父类的成员函数:

open class Parent {
    fun foo() {
        println("foo")
    }
}

class Child : Parent()

fun Child.foo() {
    println("child")
}

Child().foo()

// 输出:
// foo

相关文章

  • Kotlin原理-拓展函数

    原理 拓展函数是kotlin里一个比较常用的特性,例如我们可以给Context拓展一个toast方法: 它的原理其...

  • 详解Kotlin中的作用域函数

    Kotlin作用域函数 作用域函数,Kotlin在语法层面支持拓展函数,作用域函数,作用域函数是指对数据做一些变换...

  • Kotlin-那些好用的标准高阶函数

    Kotlin特性总结的第二篇,上一篇我们谈了拓展函数和拓展属性。本篇我们来学习一下高阶函数。 拓展函数是对类的拓展...

  • 2021-12-10

    拓展函数 高阶函数 内联函数 lamda表达式 函数式编程 jetpack kotlin 协程 flow bind...

  • Kotlin4Android学习总结三:拓展函数再举例

    上一篇已经提到了Kotlin的拓展函数,拓展函数算是目前发现的Kotlin的一个非常闪光的点,使用起来有时候有种暗...

  • Kotlin 扩展函数实现原理分析

    Kotlin 扩展函数实现原理分析 Kotlin 的扩展函数非常的方便好用,支持给现有的java类增加函数,代码如...

  • Kotlin修炼指南

    Kotlin修炼指南 作用域函数 作用域函数是Kotlin中的一个非常有用的函数,它主要分为两种,一种是拓展函数式...

  • Kotlin内联函数

    kotlin内联函数是什么? Kotlin里使用关键字 inline 来表示内联函数。其原理就是:在编译时期,把调...

  • 【kotlin】- delay函数实现原理

    简介 这片文章主要讲解kotlin中delay函数的实现原理,delay是一个挂起函数。kotlin携程使用过程中...

  • Android kotlin 点击事件防重复

    利用kotlin的拓展函数和拓展属性轻而易举实现点击事件防重复:新建一个kt文件,复制以下代码: 使用方法:

网友评论

    本文标题:Kotlin原理-拓展函数

    本文链接:https://www.haomeiwen.com/subject/aphghrtx.html