Groovy 覆盖默认调用方法
Groovy override default call method
我有以下 groovy class 作为我的 gradle 插件的一部分:
class MyClass {
final Expando someOptions
MyClass() {
someOptions = new Expando()
}
def call(Closure configure) {
configure.delegate = someOptions
configure.resolveStrategy = Closure.DELEGATE_ONLY
configure()
}
}
现在我希望用户能够通过向其添加额外的属性来配置此 class,但这些属性应存储在 someOptions
.
中
我尝试在 class 中这样做:
def call(final Closure configure) {
configure.delegate = someOptions
configure.resolveStrategy = Closure.DELEGATE_ONLY
configure()
}
插件的用户可以做:
myClass {
hello='world'
}
然而,gradle 似乎不明白 hello
属性 不存在于 myClass
实例中,而是存在于 someOptions
中class。每当我使用上述内容时,我都会收到关于 hello
不存在于 MyClass
实例中的错误。
我该怎么做?可能吗?
FWIW,它在 groovy 控制台中有效,但在 gradle.
中无效
您在插件中定义的任何 类 都不会直接在 Gradle 中使用,而是由 Gradle 包装在代理 类 中。例如,
Gradle will create a proxy class for the actual class implementation and adds (among other things) also a property setter method. The method has the name of the property and has a single argument of the same type as the property. It is different from the setProperty
and getProperty
methods already added by Groovy. For example if we have a task with a property with the name message of type String then Gradle will add the method message(String)
to the proxy class. (Source)
这就是为什么你可以在Gradle scrips中省略赋值符号的原因:
task myTask {
myProperty true // uses Gradle generated method
myProperty = true // uses Groovy generated setter
}
Gradle 还添加了一个类似于您的方法,以允许配置 DSL 中的任何对象:
myExtension {
// this works thanks to Gradle
}
如果没有这个代理方法,任何块都需要使用 Groovy 语言的方法 with(Closure)
:
myExtension.with {
// this works thanks to Groovy
}
似乎此代理方法覆盖了您示例的 call(Closure)
方法。
要解决此问题,您可以在 someOptions
上的 Groovy 中使用 Delegate
注释。这将使它的所有属性都可用于 MyClass
实例。您还可以将 someOptions
注册为 MyClass
.
的约定
编辑
在更改 call
方法的名称并显式调用它(您需要使用另一个属性 得到相同的异常)。
我有以下 groovy class 作为我的 gradle 插件的一部分:
class MyClass {
final Expando someOptions
MyClass() {
someOptions = new Expando()
}
def call(Closure configure) {
configure.delegate = someOptions
configure.resolveStrategy = Closure.DELEGATE_ONLY
configure()
}
}
现在我希望用户能够通过向其添加额外的属性来配置此 class,但这些属性应存储在 someOptions
.
我尝试在 class 中这样做:
def call(final Closure configure) {
configure.delegate = someOptions
configure.resolveStrategy = Closure.DELEGATE_ONLY
configure()
}
插件的用户可以做:
myClass {
hello='world'
}
然而,gradle 似乎不明白 hello
属性 不存在于 myClass
实例中,而是存在于 someOptions
中class。每当我使用上述内容时,我都会收到关于 hello
不存在于 MyClass
实例中的错误。
我该怎么做?可能吗?
FWIW,它在 groovy 控制台中有效,但在 gradle.
中无效您在插件中定义的任何 类 都不会直接在 Gradle 中使用,而是由 Gradle 包装在代理 类 中。例如,
Gradle will create a proxy class for the actual class implementation and adds (among other things) also a property setter method. The method has the name of the property and has a single argument of the same type as the property. It is different from the
setProperty
andgetProperty
methods already added by Groovy. For example if we have a task with a property with the name message of type String then Gradle will add the methodmessage(String)
to the proxy class. (Source)
这就是为什么你可以在Gradle scrips中省略赋值符号的原因:
task myTask {
myProperty true // uses Gradle generated method
myProperty = true // uses Groovy generated setter
}
Gradle 还添加了一个类似于您的方法,以允许配置 DSL 中的任何对象:
myExtension {
// this works thanks to Gradle
}
如果没有这个代理方法,任何块都需要使用 Groovy 语言的方法 with(Closure)
:
myExtension.with {
// this works thanks to Groovy
}
似乎此代理方法覆盖了您示例的 call(Closure)
方法。
要解决此问题,您可以在 someOptions
上的 Groovy 中使用 Delegate
注释。这将使它的所有属性都可用于 MyClass
实例。您还可以将 someOptions
注册为 MyClass
.
编辑
在更改 call
方法的名称并显式调用它(您需要使用另一个属性 得到相同的异常)。