function - 为什么 apply() 而不是函数调用
问题描述
下面的代码做同样的事情。函数tr和td将带有接收器对象的函数文字作为输入,以便在表中添加 tr 或 td 标记。
class TABLE : Tag("table") {
fun tr(init: TR.() -> Unit) {
children += TR().apply(init)
}
}
class TR : Tag("tr") {
fun td(init: TD.() -> Unit) {
val td = TD()
td.init()
children += td
}
}
我的问题是为什么我需要使用.apply()而不是:
class TABLE : Tag("table") {
fun tr(init: TR.() -> Unit) {
children += TR().init()
}
}
我想这与编译器在 tr-object 中寻找init()有关。但这不应该在运行时决定吗?
解决方案
正如我的评论中已经建议的那样,使用.apply
您可以将调用 链接init
在一起,+=
因为apply
返回其调用的目标。
如果您更喜欢使用init()
,您可以使用 获得相同的结果
val tr = TR()
children += tr
tr.init()
链式变体的关键方面是应用function of the Kotlin's standard library is defined as an extension function of a generic type
T, accepting a *lambda with receiver
作为其唯一参数,如您在此处看到的:
inline fun <T> T.apply(block: T.() -> Unit): T
为了解释它的含义,你可以自己实现这个函数:
fun <T> T.myApply(block: T.() -> Unit) : T {
this.block()
return this
}
以下示例模仿您的代码,使用假MyClass
类型代替原始类型TR
:
fun <T> T.myApply(block: T.() -> Unit) : T {
this.block()
return this
}
class MyClass(val text: String) {
fun foo() : Unit {
println("foo $text")
}
}
fun initializer(mc: MyClass) {
println("initializer ${mc.text}")
mc.foo()
}
fun run(init: MyClass.() -> Unit) {
val result = MyClass("first").myApply(init)
val x = MyClass("second")
x.init()
}
fun main(args: Array<String>) {
run(::initializer)
}
您可以使用此示例来遵循从run
到的流程MyClass.foo
,通过接受init
作为带有接收器参数的 lambda的函数:我希望这可以帮助您澄清您对原始和替代实现的关键特征的理解tr
。
推荐阅读
- android - 如何从片段中的资产读取和解析 json 文件
- javascript - 从 Seuquelize 返回然后 JavaScript 中的代码块
- python - 使用 argparse 是否可以使先前定义的参数成为必需?
- amazon-web-services - 使用 AWS-Pinpoint 将通知推送到多个设备
- google-translate - 从@google-cloud/translate 得到非常慢的响应
- spring-boot - 如何将自定义弹簧方面注释传递给建议
- html - 如何传递数组代替指向函数的指针
- kubernetes-ingress - 在 aks 中从入口控制器公开多个 tcp 端口
- ruby - Xcode 12、Mac OS 10.15、用于安装 cocoapods 的 Xcode 服务器预集成脚本
- docker - 等待容器的 Docker 错误:上下文已取消