具有接收器的Kotlin函数文字-DSL和许多库函数的基础
今天,我想快速介绍一下Kotlin 带有接收器的功能文字。这个概念使 科特林 非常适合设计 领域特定语言 as we know it from Groovy for example. Also, 科特林 's standard library includes many functions which many of you have already used or at least seen probably: apply
and with
are the most prominent ones.
前提条件
除了Java之外,Kotlin还具有 正确 功能类型,这意味着变量可以例如是“函数”类型 接受 an Int
and returning a String
": (Int)->String
. These 功能类型 can be used as parameters to other functions, which are in turn called "higher order functions":
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
As you can see myHigherOrderFun
has a parameter of a function type, which it can call in its method body. If we now want to use this higher order function, we can make use of lambdas, also referred to as "function literal":
println ( myHigherOrderFun { "The Number is $it" })
>> prints "The Number is 5"
带有接收器的Kotlin函数文字
如我们所见,函数文字可以用作其他函数的参数,这本身就是一个了不起的功能。尽管如此,Kotlin更进一步,并支持“带有接收器的函数文字”的概念。这使我们能够在 接收者 没有任何特定限定符的函数文字的形式。这非常类似于 扩展功能,也可以在扩展程序内部访问接收器对象的成员。让我们看一下函数文字是什么样的:
var greet: String.() -> Unit = { println("Hello $this") }
This one defines a variable of type String.() -> Unit
, which is basically a function type () -> Unit
with String
as the 接收者 . All methods of this 接收者 can, therefore, be called in the method body. In this example, this
is simply used to print the String
. The function can be called like so:
greet("哈迪")
>> prints "Hello 哈迪"
这基本上就是您需要知道的所有内容,让我们来看一个实际的用例。
实际中-作用域功能
正如我在开始时已经提到的那样,科特林的 标准库包含使用此概念的方法, one of which is apply
. This one is defined as follows:
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
我们可以很容易地看到, 扩展功能 从字面上看,它期望 具有通用接收器的函数文字 of type T
, which is run before the 接收者 is returned to the caller. This little function is actually fantastic as it provides a way to build certain objects very concisely and easily.
println(StringBuilder("Hello ")
.apply {
append(" 科特林 er")
append("! ")
append("How are you doing?")
}.toString())
>> prints "Hello 科特林 er! How are you doing?"
In this example, a StringBuilder
is created and then the apply
method is called on it. As we've seen before, it's possible to call any method of our 接收者 StringBuilder
like append
in the above code. Since apply
returns the 接收者 after it completes, a call of toString
on the StringBuilder
can immediately be performed and the text is printed to the console.
希望这可以帮助!我非常喜欢此功能,因为它为我们提供了许多可能性。可能是Kotlin最重要的功能之一-如果您想学习创建DSL的知识,请看一下 这里 。我自己在代码中发现了很多斑点,使用这些可识别接收者的函数可以简化很多工作;今天看看你的-
最后,如果您想了解Kotlin的美丽功能,我推荐这本书 行动中的科特林 给你!
西蒙
西蒙 是总部位于德国的软件工程师,具有7年为JVM和JavaScript编写代码的经验。他’他对尽可能多地学习新事物充满热情,并且是科特林(Kotlin)的自发狂热者。
[…]我已经在上一篇关于使用Receiver进行功能语言的文章中暗示了这一点,Kotlin旨在实现伟大的(内部)领域特定语言的创建。除了[…]
[…]允许我们创建那些DSL。这些功能之一(我也已经介绍过)称为“带有Receiver的功能文字”,其他功能是调用约定或中缀[…]
[…]很棒的事情是lambdas与接收器的用法,您可以在我的其他文章之一中了解到。 […]
[…]您可能想知道它们是如何实现的。要理解的最相关的概念称为带有接收器的函数文字(也称为带有接收器的lambda)。由于此功能对于示波器功能也至关重要,因此将在[…]
[…]我已经在上一篇关于使用Receiver进行功能语言的文章中暗示了这一点,Kotlin旨在实现伟大的(内部)领域特定语言的创建。除了[…]
您可能需要修复渲染器— you have >出现在整个地方而不是>
谢谢,但我可以’看不到错误,这还在发生吗?
恕我直言“Hadi”.greet()用于显示函数调用,而不是greet(“Hadi”)有助于更好地理解要点。感谢您分享确实有用的内容。
[…带有接收器的Lambdas […]
明确的解释,而不是打招呼(“ 哈迪”)“Hadi”.greet()恕我直言。不管怎么说,还是要谢谢你。