Kotlin带有接收者的函数类型(block: T.() -> Unit)

article/2025/9/16 18:44:22

前言

Kotlin标准库的 Standard.kt 包含几个函数,其唯一目的是在对象上下文内执行代码块。 当我们在提供了lambda表达式的对象上调用此类函数时,它将形成一个临时作用域。在此作用域中,我们可以访问没有其名称的对象,这些功能称为作用域函数。

比如我们经常使用的 applyalso 函数:

public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block()return this
}
public inline fun <T> T.also(block: (T) -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block(this)return this
}

如果我们仔细比较这两个扩展函数会发现它们非常相似:它们都接收一个 block 函数并返回 this 值。

唯一的差别就在于 apply 的 block 函数类型为:T.() -> Unit ,而 also 的 block 函数类型为:(T) -> Unit)

那么这两种函数类型到底差别在哪里呢 ?

T.() -> Unit(T) -> Unit)

首先我们看下

class Test {fun main(block: Int.() -> Unit) {val also: Class<Test> = javaClass.also {val canonicalName = it.canonicalNameprintln(canonicalName)}val apply: Class<Test> = javaClass.apply {println(canonicalName)}}
}

这样看起来不太明显,我们看下AndroidStudio的智能提示:
智能提示
这样看起来是不是简单多了,在 also 方法中接收到的是 it , 而在 apply 方法中接收到的是 this ,而表达式 it.canonicalNamecanonicalName 的差别不用我说了吧。

applythis 值作为接收者调用指定的函数[block],并返回 this 值。

alsothis 值作为参数调用指定的函数[block],并返回 this 值。

参数我们都理解,但是接收者是个什么概念,貌似从来没听过?

Kotlin的函数类型

Kotlin 使用类似 (Int) -> String 的一系列函数类型来处理函数的声明:val onClick: () -> Unit = ……

这些类型具有与函数签名相对应的特殊表示法,即它们的参数和返回值:

  • 所有函数类型都有一个圆括号括起来的参数类型列表以及一个返回类型:(A, B) -> C 表示接受类型分别为 A 与 B 两个参数并返回一个 C 类型值的函数类型。 参数类型列表可以为空,如 () -> AUnit 返回类型不可省略。
  • 函数类型可以有一个额外的接收者类型,它在表示法中的点之前指定类型: A.(B) -> C 表示可以在 A 的接收者对象上以一个 B 类型参数来调用并返回一个 C 类型值的函数。 带有接收者的函数字面值通常与这些类型一起使用。
  • 挂起函数属于特殊种类的函数类型,它的表示法中有一个 suspend 修饰符 ,例如 suspend () -> Unit 或者 suspend A.(B) -> C

函数类型表示法可以选择性地包含函数的参数名:(x: Int, y: Int) -> Point。 这些名称可用于表明参数的含义。

带有接收者的函数类型

带有接收者的函数类型,例如 A.(B) -> C,可以用特殊形式的函数字面值实例化—— 带有接收者的函数字面值

Kotlin 提供了调用带有接收者(提供接收者对象)的函数类型实例的能力。

在这样的函数字面值内部,传给调用的接收者对象成为隐式的 this,以便访问接收者对象的成员而无需任何额外的限定符,亦可使用 this 表达式 访问接收者对象

这种行为与扩展函数类似,扩展函数也允许在函数体内部访问接收者对象的成员。

为了表示当前的 接收者 我们使用 this 表达式:

  • 在类的成员中,this 指的是该类的当前对象。
  • 在扩展函数或者带有接收者的函数字面值中, this 表示在点左侧传递的 接收者 参数。
//Lambda 表达式(函数字面值)
val sum2: Int.(Int) -> Int = { other ->plus(other) //这里直接调用了Int的plus()方法,也可以写成 this.plus(other)
}

当接收者类型可以从上下文推断时,lambda 表达式可以用作带接收者的函数字面值。

参考

Kotlin:带有接收者的函数字面值

Kotlin:作用域函数


http://chatgpt.dhexx.cn/article/puTihHTD.shtml

相关文章

mysql之类型转换函数

类型转换函数 类型转换函数和case函数 1.隐式类型转换和显式类型转换的概念 隐式类型装换: 两个值进行运算或者比较,首先要求数据类型必须一致。如果发现两个数据类型不一致时就会发生隐式类型转换。例如,把字符串转成数字,或者相反: SELECT 1+‘1’; – 字符串1转成数字 …

C语言入门---函数类型与返回值(int和void)

int和void的区别&#xff1f; 哈喽&#xff0c;各位小伙伴们&#xff0c;在我们学习C语言的过程中经常会看到书中的main函数前带有int和void&#xff0c;就像下面这样&#xff1a; 上面这两种有什么区别呢&#xff1f;在C语言中&#xff0c;可以把函数分为有返回值函数和无返…

Typescript总结(三)——函数类型详解

本篇博客主要总结一下在Typescript中的函数写法&#xff0c;以及函数类型的总结。 一、Typescript的函数类型 如果在一个函数中&#xff0c;需要传入一个函数作为参数&#xff0c;可以如下所示&#xff0c;进行声明定义。 我们也可以通过type来定义函数类型 如上述代码所示…

c语言函数返回值类型必须,C++中函数类型与定义的函数返回值类型必须相同么?...

C++中函数类型与定义的函数返回值类型必须相同么?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C++中函数类型与定义的函数返回值类型必须相同么? 1.可以。只要返回值、参数列表的参数个数、类型、顺序中的一…

C语言 函数类型

1. 在 [不完全类型] 一文中,描述了C中的3大数据类型,即: 函数类型、对象类型和不完全类型, 这里再次引用这张图来进行“函数类型”的讲解。 可以看到,函数类型是对立于其他的类型的,它不像“对象类型和不完全类型”,可以延伸(或是派生)出其他对象,或是包含一子系列…

函数高级

函数&#xff1a; 1、引用传递 2、可变参数、命名参数、万能参数 3、匿名函数&#xff08;lambda&#xff09; 4、闭包&#xff08;有点难&#xff09; 5、递归 6、偏函数 7、函数作为参数传递 8、函数调用全局变量 9、全局变量和局部变量 装饰器&#xff08;函数的深层次使用…

68 4种函数类型

文章目录 1、无参数&#xff0c;无返回值的函数2、无参数&#xff0c;有返回值的函数3、有参数&#xff0c;无返回值的函数4、有参数&#xff0c;有返回值的函数5、小结 函数根据有没有参数&#xff0c;有没有返回值&#xff0c;可以相互组合&#xff0c;一共有4种 无参数&…

C语言函数之—函数的分类

目录 1. 函数是什么&#xff1f; 2. C语言中的函数分类 2.1 库函数 2.1.1 为什么会有库函数&#xff1f; 2.1.2 那怎么来学习库函数呢&#xff1f; IO函数—getchar() , putchar() 字符串操作函数—strcmp() , strlen() rand函数,srand函数 和time函数 2.1.3 如何学会…

torch.optim.Adam() 函数用法

Adam: A method for stochastic optimization Adam是通过梯度的一阶矩和二阶矩自适应的控制每个参数的学习率的大小。 adam的初始化 def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,weight_decay=0, amsgrad=False): Args:params (iterable): iterable o…

pytorch ——torch.optim.Adam

class torch.optim.Adam(params, lr0.001, betas(0.9, 0.999), eps1e-08, weight_decay0)它在Adam: A Method for Stochastic Optimization中被提出。(https://arxiv.org/abs/1412.6980) 参数&#xff1a; params (iterable) – 待优化参数的iterable或者是定义了参数组的dict…

在ADS中使用OPTIM优化设计

在ADS中可以使用OPTIM控件来对电路变量进行优化设计&#xff0c;以实现电路性能目标。ADS常用的S参数仿真和谐波平衡仿真中都可以进行优化设计。 在S参数仿真中进行优化设计 现在以一个阻抗匹配网络的设计为例&#xff0c;来展示在S 参数仿真中进行优化设计的方法。 我们搭建…

torch.optim.SGD()

其中的SGD就是optim中的一个算法&#xff08;优化器&#xff09;&#xff1a;随机梯度下降算法 PyTorch 的优化器基本都继承于 "class Optimizer"&#xff0c;这是所有 optimizer 的 base class torch.optim是一个实现了各种优化算法的库。大部分常用的方法得到支持…

torch.optim.lr_scheduler:调整学习率

本文是笔者在学习cycleGAN的代码时&#xff0c;发现其实现了根据需求选择不同调整学习率方法的策略&#xff0c;遂查资料了解pytorch各种调整学习率的方法。主要参考&#xff1a;https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate 1 综述 1.1 lr_sche…

一起来学PyTorch——torch.nn优化器optim

在学习的过程中&#xff0c;大家可能会感觉很蒙&#xff0c;其实现在做的就是看懂每一个小内容&#xff0c;等之后做一个具体的项目&#xff0c;就可以串联起来了。 优化器用于优化模型&#xff0c;加速收敛。 SGD方法 随机梯度下降法&#xff0c;是指沿着梯度下降的方向求解极…

Pytorch之Optim(优化器)

使用优化器,接收损失函数的结果,并调整网络参数,完成反向传播 根据示例 optimizer torch.optim.SGD(module.parameters(), lr0.01, momentum0.9) 然后根据提示,清空梯度>网络前传>计算损失>反向传播>优化网络参数 在运行区域引入库和之前的Module if __name__ …

torch.optim

torch.optim是一个实现了各种优化算法的库。 1. 如何使用optimizer 我们需要构建一个optimizer对象。这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。 1.1 构建 为了构建一个Optimizer&#xff0c;你需要给它一个包含了需要优化的参数&#xff08;必须都是…

torch.optim.lr_scheduler.CosineAnnealingWarmRestarts、OneCycleLR定义与使用

torch中有多种余弦退火学习率调整方法&#xff0c;包括&#xff1a;OneCycleLR、CosineAnnealingLR和CosineAnnealingWarmRestarts。 CosineAnnealingWarmRestarts&#xff08;带预热的余弦退火&#xff09;学习率方法定义 torch.optim.lr_scheduler.CosineAnnealingWarmRest…

torch.optim优化算法理解之optim.Adam()

torch.optim是一个实现了多种优化算法的包&#xff0c;大多数通用的方法都已支持&#xff0c;提供了丰富的接口调用&#xff0c;未来更多精炼的优化算法也将整合进来。 为了使用torch.optim&#xff0c;需先构造一个优化器对象Optimizer&#xff0c;用来保存当前的状态&#x…

Python-torch.optim优化算法理解之optim.Adam()

目录 简介 分析 使用 Adam算法 参数 论文理解 torch.optim.adam源码理解 Adam的特点 转载torch.optim优化算法理解之optim.Adam() 官方手册&#xff1a;torch.optim — PyTorch 1.11.0 documentation 其他参考 pytorch中优化器与学习率衰减方法总结 Adam和学习率衰减…

R 语言 optim 使用

stats中的optim函数是解决优化问题的一个简易的方法。 Univariate Optimization f function(x,a) (x-a)^2 xmin optimize(f,interval c(0,1),a1/3) xminGeneral Optimization optim函数包含了几种不同的算法。 算法的选择依赖于求解导数的难易程度&#xff0c;通常最好提…