在 Gradle 的 Kotlin DSL 中混淆 属性 委托
Confusing Property Delegation in Gradle's Kotlin DSL
下面是我在 gradle 的文档中看到的代码片段
https://docs.gradle.org/current/userguide/tutorial_using_tasks.html
val hello by tasks.registering {
doLast {
println("Hello Earth")
}
}
hello {
doFirst {
println("Hello Venus")
}
}
上面hello是TaskProvider类型,提供任务definition/action。第二次调用 hello 是为了扩展任务的行为。
这个 delegate 使用看起来有点让我困惑。以下是困扰我的问题:
1) 在检查反编译的字节码时,我看到 tasks.registering returns RegisteringDomainObjectDelegateProviderWithAction 对象应该用作委托,因此应该为 delegate 提供 getValue() 和 setValue() 方法,但正如我所见,没有提供方法。相反,class RegisteringDomainObjectDelegateProviderWithAction 有一个 delegateProvider 属性 类型 tasks 哪个应该提供 delegate。任何人都可以帮助我理解委托在这里是如何工作的吗?
2) 第二次调用应该向 hello 任务添加行为。由于 hello 是一个 属性,我们如何才能将 lambda/behavior 传递给它呢?我错过了什么?
我已经看过 kotlin 文档,它提供了对委托的很好解释,但无助于理解上述情况 https://kotlinlang.org/docs/reference/delegated-properties.html
我是 Kotlin 的新手,希望能有详细的解释。
关于委托使用:
委托通过在 RegisteringDomainObjectDelegateProviderWithAction
上定义的扩展运算符方法 provideDelegate
工作:
operator fun RegisteringDomainObjectDelegateProviderWithAction<out TaskContainer, Task>.provideDelegate(
receiver: Any?,
property: KProperty<*>
) = ExistingDomainObjectDelegate.of(
delegateProvider.register(property.name, action)
)
provideDelegate
运算符允许在委托创建中使用更复杂的逻辑。根据 docs:
By defining the provideDelegate
operator you can extend the logic of creating the object to which the property implementation is delegated. If the object used on the right hand side of by defines provideDelegate
as a member or extension function, that function will be called to create the property delegate instance.
关于"passing a lambda to a property":
这是通过重载 invoke
operator 作为 TaskProvider
上的扩展函数实现的 class:
operator fun <T> NamedDomainObjectProvider<T>.invoke(action: T.() -> Unit) =
configure(action)
基本上,调用 hello { /* your lambda */ }
被脱糖为 hello.invoke { /* your lambda */ }
。
下面是我在 gradle 的文档中看到的代码片段 https://docs.gradle.org/current/userguide/tutorial_using_tasks.html
val hello by tasks.registering {
doLast {
println("Hello Earth")
}
}
hello {
doFirst {
println("Hello Venus")
}
}
上面hello是TaskProvider类型,提供任务definition/action。第二次调用 hello 是为了扩展任务的行为。
这个 delegate 使用看起来有点让我困惑。以下是困扰我的问题:
1) 在检查反编译的字节码时,我看到 tasks.registering returns RegisteringDomainObjectDelegateProviderWithAction 对象应该用作委托,因此应该为 delegate 提供 getValue() 和 setValue() 方法,但正如我所见,没有提供方法。相反,class RegisteringDomainObjectDelegateProviderWithAction 有一个 delegateProvider 属性 类型 tasks 哪个应该提供 delegate。任何人都可以帮助我理解委托在这里是如何工作的吗?
2) 第二次调用应该向 hello 任务添加行为。由于 hello 是一个 属性,我们如何才能将 lambda/behavior 传递给它呢?我错过了什么?
我已经看过 kotlin 文档,它提供了对委托的很好解释,但无助于理解上述情况 https://kotlinlang.org/docs/reference/delegated-properties.html
我是 Kotlin 的新手,希望能有详细的解释。
关于委托使用:
委托通过在
RegisteringDomainObjectDelegateProviderWithAction
上定义的扩展运算符方法provideDelegate
工作:operator fun RegisteringDomainObjectDelegateProviderWithAction<out TaskContainer, Task>.provideDelegate( receiver: Any?, property: KProperty<*> ) = ExistingDomainObjectDelegate.of( delegateProvider.register(property.name, action) )
provideDelegate
运算符允许在委托创建中使用更复杂的逻辑。根据 docs:By defining the
provideDelegate
operator you can extend the logic of creating the object to which the property implementation is delegated. If the object used on the right hand side of by definesprovideDelegate
as a member or extension function, that function will be called to create the property delegate instance.关于"passing a lambda to a property":
这是通过重载
invoke
operator 作为TaskProvider
上的扩展函数实现的 class:operator fun <T> NamedDomainObjectProvider<T>.invoke(action: T.() -> Unit) = configure(action)
基本上,调用
hello { /* your lambda */ }
被脱糖为hello.invoke { /* your lambda */ }
。