在下面的代码中,modelInitializer 的参数类型是
CalendarMonthTitleModelBuilder.()
什么.()意思?。我相信点是指扩展。当你add ()追求它时,我认为这意味着创建一个这种类型的实例。这是否意味着在此处创建并初始化了一些匿名扩展?
inline fun EpoxyController.calendarMonthTitle(modelInitializer: CalendarMonthTitleModelBuilder.() ->
Unit) {
CalendarMonthTitleModel_().apply {
modelInitializer()
}
.addTo(this)
}
Run Code Online (Sandbox Code Playgroud)
如果你之前省略了点会发生什么()?
正确的名称是带有接收器的 lambda
你已经朝着正确的方向开始了。所以一个简单的方法是从扩展函数开始:
fun CalendarMonthTitleModelBuilder.foo() = //...
Run Code Online (Sandbox Code Playgroud)
该函数foo是类型上的扩展函数CalendarMonthTitleModelBuilder。
让我们从另一个角度来看待它。让我们来谈谈高阶函数,也就是将其他函数作为参数的函数:
fun higherOrder(func: () -> Unit) = //...
Run Code Online (Sandbox Code Playgroud)
此函数接收lambda不接收任何参数并返回的Unit。如果我们想CalendarMonthTitleModelBuilder在 lambda 内部使用 a 可以做什么?一个简单的方法是传入它:
fun higherOrder(func: (CalendarMonthTitleModelBuilder) -> Unit) = //...
Run Code Online (Sandbox Code Playgroud)
调用这个函数,会是这样的:
higherOrder {
it.someMethod()
}
Run Code Online (Sandbox Code Playgroud)
(这里 someMethod 是 CalendarMonthTitleModelBuilder 的一部分)
但是,我们可以CalendarMonthTitleModelBuilder通过对扩展函数使用类似的语法,以某种方式使这个 lambda 成为扩展:
fun higherOrder(func: CalendarMonthTitleModelBuilder.() -> Unit) = //...
Run Code Online (Sandbox Code Playgroud)
现在的区别在于,我们创建了一个带接收器的 lambda,这意味着it我们可以使用this,或者更好的是,省略它,而不是使用隐式参数:
higherOrder {
someMethod()
}
Run Code Online (Sandbox Code Playgroud)
在 lambda 内部,this是 的一个实例CalendarMonthTitleModelBuilder,因此您可以简单地调用someMethod.
这些构造经常在 DSL 中使用,并且您在像您这样的示例中经常看到它们 - 使用构建器模式。
这是一个非常简单的例子。假设您有UserBuilder一个构建用户的类,并且您想为此创建一个小的 DSL(这是对模式的夸大,但我认为适合提供帮助):
data class User(
val email: String,
val password: String)
class UserBuilder {
var email: String = ""
var password: String = ""
fun build() = User(email, password)
}
Run Code Online (Sandbox Code Playgroud)
可以从编写一个高阶函数开始,如下所示:
fun user(func: UserBuilder.() -> Unit) =
UserBuilder().apply(func)
Run Code Online (Sandbox Code Playgroud)
在方法内部,我们创建了一个构建器的实例并将 lambda 应用到它。这是一个简单的技巧,因此我们可以继续链接方法并在最后调用build。例如:
user {
email = "foo@bar.com"
password = "123456"
}.build()
Run Code Online (Sandbox Code Playgroud)
使用扩展函数可以走得更远:
fun UserBuilder.withEmail(emailBuilder: () -> String) {
email = emailBuilder()
}
Run Code Online (Sandbox Code Playgroud)
让你做:
user {
withEmail {
"foo@bar.com"
}
}.build()
Run Code Online (Sandbox Code Playgroud)
我们可以调用withEmailinsideuser是因为withEmailon 是一个扩展函数,UserBuilder而 insideuser this是UserBuilder具有接收器的 lambda类型。
您可以执行类似于密码的操作。
| 归档时间: |
|
| 查看次数: |
370 次 |
| 最近记录: |