groovy 如何在继承类中继承静态生成器/构造器方法?

yk9xbfzb  于 2023-03-11  发布在  其他
关注(0)|答案(2)|浏览(172)

我尝试使用Groovy Closure为静态构造器实现一个公共接口,其中,我尝试实现的模式是:

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);
    }
}

正如任何有经验的Java开发人员可能会注意到的那样,语法Class<T> clazz = T是无效的,因为T是类型签名,而不是实际的类定义。同时,我已经在那里放置了一个错误throw new Error('Not implemented');,但这样做我失去了with方法的公共接口,而with方法是必需的实现。并且WithBuilder的任何子类都应该返回该类的新示例。
任何关于如何得到这个的提示将不胜感激。我正在尝试构建一个流畅的构建器,在实践中看起来像这样:

import pipeline.Configuration
import pipeline.Credentials
import pipeline.languages.SupportedLanguages

Configuration.with {
    language SupportedLanguages.Java
    credentials Credentials.get('user')
    environments {
        dev()
    }
}

注意:以上内容并不完全是代码,但这是我希望它如何工作的方向。我还在学习Groovy闭包,因此以上内容可能无效,但我受到了Jenkins声明性语法的启发,因此我的目标是类似的东西。

编辑#1

一条很有帮助的评论指出我遗漏了一个澄清。他们认为静态方法上遗漏类型参数是一个意外,但这多少是故意的,尽管我忘记了指出我知道它不会那样工作。原因是我希望继承的类能够像这样使用它:

class MyClass extends WithBuilder<<MyClass> {
    @Override
    static MyClass with(Closure<MyClass> builder) {
        return with(MyClass, builder);
    }
}

但是,在我的示例中,我收到Method does not override method from its super class的警告

nnsrf1az

nnsrf1az1#

在您的情况下,不需要继承。以下是可行的:

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
}

和输出:

MyClass [a=1]
tcbh2hod

tcbh2hod2#

我知道我不是在回答这个问题。我只是在试着展示另一种方法来达到问题中描述的目标。
groovy方法来声明Class类上的元类方法-因此,with方法将出现在任何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

相关问题