当前位置: 首页 > 知识库问答 >
问题:

Gradle的Kotlin DSL中令人困惑的属性委托

郗浩言
2023-03-14

下面是我在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类型。对hello的第二个调用是扩展任务的行为。

这个委托使用看起来有点让我困惑。以下是困扰我的问题:

1) 在检查反编译的字节码时,我看到了任务。注册返回RegisteringDomainObjectDelegateProviderWithAction对象,该对象应作为委托使用,因此应为委托提供getValue()和setValue()方法,但正如我所见,没有提供方法。相反,类RegisteringDomainObjectDelegateProviderWithAction具有类型为tasks的delegateProvider属性,该属性应该提供委托。有人能帮助我理解代表团是如何在这里工作的吗?

2)第二次调用应该向hello任务添加行为。由于hello是一个属性,我们如何将lambda/行为传递给它?我缺少什么?

我已经看到kotlin留档,它提供了很好的代表解释,但并不有助于理解上述情况https://kotlinlang.org/docs/reference/delegated-properties.html

由于我是科特林的新手,我希望得到详细的解释。

共有1个答案

狄心水
2023-03-14

>

  • 关于代表使用:

    委派通过扩展运算符方法工作,提供注册域对象委派提供器上定义的委派:

    operator fun RegisteringDomainObjectDelegateProviderWithAction<out TaskContainer, Task>.provideDelegate(
        receiver: Any?,
        property: KProperty<*>
    ) = ExistingDomainObjectDelegate.of(
        delegateProvider.register(property.name, action)
    )
    

    < code>provideDelegate运算符允许在委托创建中使用更复杂的逻辑。根据文件:

    通过定义供应委托运算符,您可以扩展创建属性实现委托给的对象的逻辑。如果by右侧使用的对象将供应委托定义为成员或扩展函数,则将调用该函数来创建属性委托实例。

    关于“将lambda传递给属性”:

    这是通过重载调用运算符作为 TaskProvider 类上的扩展函数来实现的:

    operator fun <T> NamedDomainObjectProvider<T>.invoke(action: T.() -> Unit) =
        configure(action)
    

    基本上,调用<code>hello{/*您的lambda*/}中调用{/*。

  •  类似资料:
    • 我希望类中的方法在IO线程上运行一些代码,但只有一次它们订阅的主题具有特定值。然后调用者应该在AndroidUI线程上得到响应。 像这样的东西: 这有用吗?不确定,所以我写了一组单元测试来检查它们。我发现我的测试方法,尽管它们在一个接一个地运行时总是有效的,但作为套件的一部分会失败。 事实上,我发现如果我把同样的测试进行两次,第一次会通过,但第二次会失败! 为什么会这样?被测类中的bug是,还是测

    • 这是一个练习2D数组的练习,显然我在理解它们方面失败了。输入是创建一个方法,该方法在数组[][]中查找最大的沙漏形整数数。数组的大小总是6x6,因此循环是x<4和y<4,整数值也是从-9到9,这就是为什么我的结果变量以-256开始(如果我以0开始,充满负值的数组将不起作用) 样本输入 即产生输出的沙漏形状 然后在main中使用我的biggestHourglass()方法。 我的结果不符合预期,我不

    • 问题内容: 有人可以向我解释一下吗: 我从不理解,我认真地认为,如果有人不尝试向我深入解释,我永远也不会。这整个上下文使我感到困惑。有时它是这样的: 有时它不会那样工作,但只接受: 有时是: 等等等等等。 我了解上下文的基础,但是有几项?为什么日食会一次又一次地向我抛出错误呢?为什么有时需要声明上下文?: 我无法在所有情况下都找到合适的环境,我怎么知道在每种情况下都合适的环境? 问题答案: 首先,

    • 错误:错误:CreateProcess:没有这样的文件或目录 Gradle控制台中的详细日志是: 失败:生成失败,出现异常。 很高兴提到在这个错误之前,我有一个“在结构中重新定义”的错误。当我集中精力时,我发现在两个link.h文件中有两个类的重复定义,一个在项目中,另一个在我的sdk\ndk-bundle目录中。所以我在我的sdk中评论了link.h中的冲突,我就面临了上面的错误。但奇怪的是,当

    • 问题内容: 我总是将If语句(在C#中)用作(1.替代); 我知道没有必要将“ == true”写为(2.替代)); 但是,我使用它是因为它更具可读性,并且不会引起性能问题。当然,这是我的选择,而且我知道许多软件开发人员都喜欢第一种选择。最佳用法是什么,为什么? 问题答案: 如果布尔值的名称清楚地说明了它的含义,那么我将始终选择版本2。但是,有时您会陷入一个特别晦涩的变量名,至少不能更改它。现在就

    • 我试图理解java.util.random.NextInt(int n)是如何工作的,尽管进行了所有的搜索甚至调试,但我还是不能完全理解它的实现。 造成混乱的是while循环:http://docs.oracle.com/javase/7/docs/api/java/util/random.html#NextInt(int) 我意识到这应该是为了解决模数偏见,但很难看到如何解决。