混淆理解 lambda 和接收器
Confusion with understanding lambda and receivers
Kotlin 版本 1.2.50
我一直在关注 YouTube 上本教程的一些示例 https://www.youtube.com/watch?v=gPH9XnvpoXE。并且有几件事我已经明白了,但还是有些迷茫。我在下面的代码中留下了我不确定发生了什么的评论。
fun main(args: Array<String>) {
val javaClient = createClient {
firstName = "joe"
lastName = "bloggs"
twitter {
handle = "@joebloggs"
}
}
println(javaClient.toConsole)
}
/* Are we passing in a lambda and receiver. What will the receiver be */
private fun JavaClientBuilder.twitter(suppler: JavaTwitterBuilder.() -> Unit) {
/* We call JavaTwitterBuilder().apply(..) Will apply return the newly created object? Not sure why we have to pass the suppler in the apply */
twitter = JavaTwitterBuilder().apply(suppler).build()
}
/* Are we passing in a lambda and receiver that return nothing */
private fun createClient(suppler: JavaClientBuilder.() -> Unit): JavaClient {
val javaClientBuilder = JavaClientBuilder()
/* confusion: Not sure about this, as we are calling suppler. Just wondering is the suppler the the JavaClientBuilder that was called in the above javaClient {} lambda */
javaClientBuilder.suppler()
return javaClientBuilder.build()
}
/* I understand this, an extension function that formats and returns the string from the JavaClient object it was called on */
private val JavaClient.toConsole: String
get() =
"Created client is: ${twitter.handle} ${company.name}"
/* Are we passing in a lambda and receiver. What will the receiver be */
private fun JavaClientBuilder.twitter(suppler: JavaTwitterBuilder.() -> Unit)
我们确实在这个函数中有一个接收器,它是 JavaClientBuilder
的实例,这个函数将被调用。
/* We call JavaTwitterBuilder().apply(..) Will apply return the newly created object? Not sure why we have to pass the suppler in the apply */
twitter = JavaTwitterBuilder().apply(suppler).build()
要了解 apply()
的工作原理,请查看其源代码(简化版):
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
它是一个扩展函数,在 T
类型的接收器上声明并返回一个 T
的实例,它接收一个块 - 另一个扩展函数 T
类型的接收器返回Unit
。它通常用于替换 Builder 模式 - 将自定义初始化逻辑应用于对象。在您的例子中,suppler
是一个包含 JavaTwitterBuilder
实例的初始化逻辑的块。函数代码创建实例并使用 apply()
和 suppler
中的逻辑来初始化该实例。
/* Are we passing in a lambda and receiver that return nothing */
private fun createClient(suppler: JavaClientBuilder.() -> Unit): JavaClient
在这种情况下,createClient()
没有接收器,它是一个顶级函数。
/* confusion: Not sure about this, as we are calling suppler. Just wondering is the suppler the the JavaClientBuilder that was called in the above javaClient {} lambda */
javaClientBuilder.suppler()
suppler
是一个 lambda,JavaClientBuilder
是接收者类型,这允许我们在新创建的 JavaClientBuilder
.
实例上调用它
/* I understand this, an extension function that formats and returns the string from the JavaClient object it was called on */
private val JavaClient.toConsole: String
get() =
"Created client is: ${twitter.handle} ${company.name}"
对了!只是一个小的更正,它是一个 扩展 属性。属性可以有自定义 getters 和设置器。这个 属性 定义了一个自定义的 getter,所以实际上每当这个 属性 被访问时它都会产生一个字符串,其格式由 getter 代码描述。
希望以下示例有助于理解具有接收器类型的 lambda:
data class Person(val name: String)
fun getPrefixSafely(
prefixLength: Int,
person: Person?,
getPrefix: Person.(Int) -> String): String
{
if (person?.name?.length ?: 0 < prefixLength) return ""
return person?.getPrefix(prefixLength).orEmpty()
}
// Here is how getPrefixSafely can be called
getPrefixSafely(
prefixLength = 2,
person = Person("name"),
getPrefix = { x -> this.name.take(x) }
)
PS: 这些具有接收者类型的函数文字类似于扩展函数 IMO。
Kotlin 版本 1.2.50
我一直在关注 YouTube 上本教程的一些示例 https://www.youtube.com/watch?v=gPH9XnvpoXE。并且有几件事我已经明白了,但还是有些迷茫。我在下面的代码中留下了我不确定发生了什么的评论。
fun main(args: Array<String>) {
val javaClient = createClient {
firstName = "joe"
lastName = "bloggs"
twitter {
handle = "@joebloggs"
}
}
println(javaClient.toConsole)
}
/* Are we passing in a lambda and receiver. What will the receiver be */
private fun JavaClientBuilder.twitter(suppler: JavaTwitterBuilder.() -> Unit) {
/* We call JavaTwitterBuilder().apply(..) Will apply return the newly created object? Not sure why we have to pass the suppler in the apply */
twitter = JavaTwitterBuilder().apply(suppler).build()
}
/* Are we passing in a lambda and receiver that return nothing */
private fun createClient(suppler: JavaClientBuilder.() -> Unit): JavaClient {
val javaClientBuilder = JavaClientBuilder()
/* confusion: Not sure about this, as we are calling suppler. Just wondering is the suppler the the JavaClientBuilder that was called in the above javaClient {} lambda */
javaClientBuilder.suppler()
return javaClientBuilder.build()
}
/* I understand this, an extension function that formats and returns the string from the JavaClient object it was called on */
private val JavaClient.toConsole: String
get() =
"Created client is: ${twitter.handle} ${company.name}"
/* Are we passing in a lambda and receiver. What will the receiver be */
private fun JavaClientBuilder.twitter(suppler: JavaTwitterBuilder.() -> Unit)
我们确实在这个函数中有一个接收器,它是 JavaClientBuilder
的实例,这个函数将被调用。
/* We call JavaTwitterBuilder().apply(..) Will apply return the newly created object? Not sure why we have to pass the suppler in the apply */
twitter = JavaTwitterBuilder().apply(suppler).build()
要了解 apply()
的工作原理,请查看其源代码(简化版):
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
它是一个扩展函数,在 T
类型的接收器上声明并返回一个 T
的实例,它接收一个块 - 另一个扩展函数 T
类型的接收器返回Unit
。它通常用于替换 Builder 模式 - 将自定义初始化逻辑应用于对象。在您的例子中,suppler
是一个包含 JavaTwitterBuilder
实例的初始化逻辑的块。函数代码创建实例并使用 apply()
和 suppler
中的逻辑来初始化该实例。
/* Are we passing in a lambda and receiver that return nothing */
private fun createClient(suppler: JavaClientBuilder.() -> Unit): JavaClient
在这种情况下,createClient()
没有接收器,它是一个顶级函数。
/* confusion: Not sure about this, as we are calling suppler. Just wondering is the suppler the the JavaClientBuilder that was called in the above javaClient {} lambda */
javaClientBuilder.suppler()
suppler
是一个 lambda,JavaClientBuilder
是接收者类型,这允许我们在新创建的 JavaClientBuilder
.
/* I understand this, an extension function that formats and returns the string from the JavaClient object it was called on */
private val JavaClient.toConsole: String get() = "Created client is: ${twitter.handle} ${company.name}"
对了!只是一个小的更正,它是一个 扩展 属性。属性可以有自定义 getters 和设置器。这个 属性 定义了一个自定义的 getter,所以实际上每当这个 属性 被访问时它都会产生一个字符串,其格式由 getter 代码描述。
希望以下示例有助于理解具有接收器类型的 lambda:
data class Person(val name: String)
fun getPrefixSafely(
prefixLength: Int,
person: Person?,
getPrefix: Person.(Int) -> String): String
{
if (person?.name?.length ?: 0 < prefixLength) return ""
return person?.getPrefix(prefixLength).orEmpty()
}
// Here is how getPrefixSafely can be called
getPrefixSafely(
prefixLength = 2,
person = Person("name"),
getPrefix = { x -> this.name.take(x) }
)
PS: 这些具有接收者类型的函数文字类似于扩展函数 IMO。