英文:
How to inherit static builder/constructor method in inherited class?
问题
static T with(Closure<T> builder) {
def clazz = T
return with(clazz, builder)
}
static <T> T with(Class<T> clazz, Closure<T> builder) {
T arg = clazz.getDeclaredConstructor().newInstance()
builder.delegate = arg
builder.resolveStrategy = Closure.DELEGATE_ONLY
return builder(arg)
}
英文:
I'm trying to implement a common interface for static constructers using a Groovy Closure
. In it, the pattern I'm attempting to implement is:
abstract class WithBuilder<T> {
static T with(Closure<T> builder) {
Class<T> clazz = T;
return with(clazz, builder);
}
static <T> T with(Class<T> clazz, Closure<T> builder) {
T arg = clazz.getDeclaredConstructor().newInstance();
builder.delegate = arg;
builder.resolveStrategy = Closure.DELEGATE_ONLY;
return builder(arg);
}
}
As any experienced Java developer might note, the syntax Class<T> clazz = T
isn't valid because T
is a type signature and not an actual class definition. In the meantime, I've taken to putting an error there throw new Error('Not implemented');
but in doing so I lose the common interface of the with
method being a required implementation, and that any subclass of WithBuilder
should return a new instance of the class.
Any tips on how to get this would be appreciated. I'm trying to build a fluent builder that would look like this in practice:
import pipeline.Configuration
import pipeline.Credentials
import pipeline.languages.SupportedLanguages
Configuration.with {
language SupportedLanguages.Java
credentials Credentials.get('user')
environments {
dev()
}
}
Note: the above is not quite code, but it's the direction I'm aiming for how I want this to work. I'm still learning about Groovy Closures, so the above might not be valid, but I've been inspired by the Jenkins declarative syntax and so I'm aiming for something like that.
Edit #1
A helpful comment pointed out I was missing a clarification. They thought the missing type parameter on a static method was an accident, but it was somewhat intentional, though I forgot to call out that I know it won't work that way. The reason for it is I want the inherited class to be able to use it like this:
class MyClass extends WithBuilder<<MyClass> {
@Override
static MyClass with(Closure<MyClass> builder) {
return with(MyClass, builder);
}
}
However, in my case, I get a warning that Method does not override method from its super class
答案1
得分: 1
在你的情况下,不需要使用继承。可以这样做:
英文:
In your case there is no need for inheritance. This would work:
class Helper {
static <T> T with(Class<T> clazz, Closure<?> builder) {
T arg = clazz.getDeclaredConstructor().newInstance();
builder.delegate = arg;
builder.resolveStrategy = Closure.DELEGATE_ONLY;
builder(arg)
return arg; // not builder call result, but delegate
}
}
class MyClass {
int a
static MyClass with(@DelegatesTo(MyClass.class) Closure<?> builder) {
return Helper.with(MyClass.class, builder);
}
@Override
String toString() {
return "MyClass [a=$a]"
}
}
println MyClass.with {
a = 1
}
And output:
MyClass [a=1]
答案2
得分: 1
我知道我没有回答问题。只是试图展示实现问题描述的目标的另一种方式。
在Class
类上声明元类方法的Groovy方式 - 因此,with
方法将出现在任何Class
引用上:
Class.metaClass.with={Closure builder->
var arg = delegate.newInstance()
builder.delegate = arg
builder.resolveStrategy = Closure.DELEGATE_ONLY
builder(arg)
return arg
}
//用自定义类进行测试
class MyClass {
int abc
}
assert 123 == MyClass.with{
abc=123
}.abc
//用标准类进行测试
assert 'abc-123' == StringBuilder.with{
it << 'abc' << '-' << 123
}.toString()
https://docs.groovy-lang.org/latest/html/documentation/core-metaprogramming.html#_metaclasses
英文:
i know that i'm not answering the question. just trying show alternative way to achieve the goal described in question.
groovy way to declare a metaclass method on a Class
class - so, with
method will appear on any Class
ref:
Class.metaClass.with={Closure builder->
var arg = delegate.newInstance()
builder.delegate = arg
builder.resolveStrategy = Closure.DELEGATE_ONLY
builder(arg)
return arg
}
//test with custom class
class MyClass {
int abc
}
assert 123 == MyClass.with{
abc=123
}.abc
//test with standard class
assert 'abc-123' == StringBuilder.with{
it << 'abc' << '-' << 123
}.toString()
https://docs.groovy-lang.org/latest/html/documentation/core-metaprogramming.html#_metaclasses
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论