了解初始化为扩展功能的参数 [英] Understanding a parameter that is initialized as an extension function

查看:119
本文介绍了了解初始化为扩展功能的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下代码中,modelInitializer的参数类型为 CalendarMonthTitleModelBuilder.()

In the following code the parameter type for modelInitializer is CalendarMonthTitleModelBuilder.()

.()是什么意思?我相信该点是指扩展名.当您在add ()之后,我认为这意味着创建此类型的实例.这是否意味着在此处创建了一些匿名扩展名并对其进行了初始化?

What does the .() mean?. I believe the dot refers to an extension. And when you add () after it, I think it means to create an instance of this type. Does this mean some anonymous extension is being created here and initialized?

inline fun EpoxyController.calendarMonthTitle(modelInitializer: CalendarMonthTitleModelBuilder.() ->
        Unit) {
    CalendarMonthTitleModel_().apply  {
        modelInitializer()
    }
    .addTo(this)
}

如果您在()之前留了点,会发生什么?

What happens if you leave out the dot before ()?

推荐答案

正确的名称称为您已朝着正确的方向开始.因此,想到这一点的简单方法是从扩展功能开始:

You've started in the right direction. So an easy way to think of this is by starting in extension functions:

fun CalendarMonthTitleModelBuilder.foo() = //...

函数fooCalendarMonthTitleModelBuilder类型的扩展功能.

The function foo is an extension function on the type CalendarMonthTitleModelBuilder.

让我们从另一个角度来对待它.让我们来谈谈以其他函数为参数的高阶函数(又称函数):

Let's approach it from another angle. Let's talk about higher-order functions, a.k.a. functions that take other functions as parameters:

fun higherOrder(func: () -> Unit) = //...

此函数接收一个lambda,该lambda不接收任何参数并返回Unit.如果我们想在lambda中使用CalendarMonthTitleModelBuilder,该怎么办?一种简单的方法是将其传递给:

This function receives a lambda that receives no parameters and returns Unit. What could one do if we wanted to use a CalendarMonthTitleModelBuilder inside the lambda? An easy way is to pass it in:

fun higherOrder(func: (CalendarMonthTitleModelBuilder) -> Unit) = //...

调用此函数将是这样的:

Calling this function, would be something like this:

higherOrder {
   it.someMethod()
}

(此处someMethod是CalendarMonthTitleModelBuilder的一部分)

但是,我们可以通过使用与扩展功能类似的语法,将此lambda扩展为CalendarMonthTitleModelBuilder:

However, we can somehow make this lambda an extension to CalendarMonthTitleModelBuilder by using a similar sytax to the extension functions:

fun higherOrder(func: CalendarMonthTitleModelBuilder.() -> Unit) = //...

现在的区别是,我们创建了一个带有接收器的lambda,这意味着我们可以使用this,或者可以省略它,而不是使用隐式参数it:

The difference now, is that we've created a lambda with receiver, meaning instead of using the implicit parameter it, we can use this, or better yet, omit it:

higherOrder {
   someMethod()
}

在lambda内的

中,thisCalendarMonthTitleModelBuilder的实例,因此您可以简单地调用someMethod.

inside the lambda, this is an instance of CalendarMonthTitleModelBuilder, so you can simply call someMethod.

这些构造通常用于DSL中,在带有构建器模式的示例中,您会经常看到它们.

These constructs are often used in DSL's and you see them a lot in examples like yours - with the builder pattern.

这是一个非常简单的示例.假设您有UserBuilder类来构建用户,并且您想要为此创建一个小型DSL(这是模式的一种夸张,但我认为很适合帮助您):

Here's a very simple example. Let's assume you have UserBuilder class that builds users and you want to create a small DSL for this (this is an exaggeration of the pattern, but suits to help out I think):

data class User(
    val email: String,
    val password: String)

class UserBuilder {
    var email: String = ""
    var password: String = ""

    fun build() = User(email, password)
}

一个人可以先编写一个像这样的高阶函数:

One can begin by writing a higher-order function like so:

fun user(func: UserBuilder.() -> Unit) =
    UserBuilder().apply(func)

在方法内部,我们创建了构建器的实例,并将其应用于lambda.这是一个简单的技巧,因此我们可以继续链接方法,并在最后调用build.例如:

Inside the method, we create an instance of the builder and apply to it the lambda. This is a simple trick so we can keep on chaining the methods and at the end call build. For example:

user {
    email = "foo@bar.com"
    password = "123456"
}.build()

使用扩展功能甚至可以走得更远:

It's possible to go even further using extension functions:

fun UserBuilder.withEmail(emailBuilder: () -> String) {
  email = emailBuilder()
}

让我们来做什么:

user {
    withEmail {
        "foo@bar.com"
    }
}.build()

我们可以在user内调用withEmail,因为withEmailUserBuilder上的扩展功能,而user this内的类型是UserBuilder,这是因为带有接收器的lambda.

we can call withEmail inside user because withEmail is an extension function on UserBuilder and inside user this is of type UserBuilder due to the lambda with receiver.

您可以执行类似于密码的操作.

You can do something similar to the password.

这篇关于了解初始化为扩展功能的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆