kotlin之带接收者的函数字面量

在kotlin中,带接受者的函数字面量这个使用的地方还是很多的,需要仔细理解总结一下

在java中,函数(在java了,把函数称方法)是定义在类里面的,在调用函数的时候,都是先new一个类对象,然后,通过.调用函数。其实调用方法的过程,是把类对象传给了方法,这个也是java常说的一个概念,就是方法有个默认参数是类对象。

在Kotlin中,由于函数是first class(一等公民),类的地位被弱化了,所以好多设计都是围绕函数来的(函数式编程),java是面向对象编程的语言。接受者可以类比于java的类,也是用.操作符的,在实际使用的时候,也是用对象调用方法的,在函数体中,this也是表示调用方法的对象,我理解其实也是给方法传入了一个类对象。把kotlin的这种函数定义叫“扩展函数”

先看一个简单的带接收者的lambda表达式的例子

    var subtract : Int.(Int) -> Int = {this - it}
    println(3.subtract(2))

这个很好理解,带接收者的lambda表达式也是可以作为函数参数的,这个需要理解一下,我们看看kotlin标准库里面的run方法

/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

首先run函数(方法),它自身是带接收者的,接收者类型是T,T是一个范型,就理解成一个具体的类型就行。在run函数的函数体内,我们知道this可以操作这个接收者的,看第一个例子就明白了。然后我们看看run的参数,参数是个函数类型的,不过这里是带接收者的,也就是说在run函数体内是这样使用的:

T类型的接收者实例.block()

在run方法内,this就是一个T类型的接收者实例,this可以省略,所以我们看到是block()这样的调用,这样,block具体代表的函数,其函数体内的this,就是调用run的T类型的接收者实例

好啦,具体细节分析完了,我们抽象出来看,就是:传给run一个函数,函数体内可以访问调用run的实例。看一个例子

        val mTvBtn = findViewById<TextView>(R.id.text)
        mTvBtn.run{
            text = "kotlin"
            textSize = 13f
        }

这样的代码一看就很简洁呀,也知道这是要干嘛,这个就是给TextView的属性赋值

说明一下:run方法的参数是 () -> R类型的,这个意思就是这个函数没有参数,返回类型是R类型。对有没有参数的函数,lambda表达式中->和->前面的都可以省略掉。而且看这个意思,没有指定具体R类型,说明也是没有的,是没有返回值的。所以我们才看到有上面的代码样子

kotlin的标准库里还提供了不带接收者的run方法,我们也看一下

/**
 * Calls the specified function [block] and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run).
 */
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
package com.lzy.learnpro

import android.app.Activity
import android.os.Bundle
import android.widget.TextView

/**
 * @Author  zhongyili
 * @Date 2020/4/7
 */
class SecondActivity: Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val mTvBtn = findViewById<TextView>(R.id.text)

        mTvBtn.run{
            text = "kotlin"
            textSize = 13f
            //这个this是mTvBtn
            println(this)
        }

        //这个run方法相当于kotlin类的静态方法
        kotlin.run {
            mTvBtn.text = "kotlin"
            mTvBtn.textSize = 13f
            //这个this是SecondActivity
            println(this)
        }

        //这个run的接收者是this,也就是SecondActivity,只是省略掉了
        run {
            mTvBtn.text = "kotlin"
            mTvBtn.textSize = 13f
            //这个this是SecondActivity
            println(this)
        }



    }
}

2021年4月19日更新

扩展函数无非就是静态函数的高级语法糖。在kotlin中使用的时候,感觉是一个类的成员函数,其实是个静态函数,在java中使用的方式就是静态函数的形式。扩展函数因为实际是静态函数,所以,是不能重写的。

Kotlin-Extension Functions(扩展函数)实现原理分析

带接收者的函数字面值与解构声明详解

Kotlin——高级篇(二):高阶函数详解与标准的高阶函数使用

Kotlin与Java:this关键字

第八章 Kotlin之This,inner关键字

Kotlin的inline内联函数

简单理解 Kotlin 中的 inline 关键字


 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值