如何在子类中继承静态Builder/构造方法?
Groovy Closure通用静态构建器接口实现方案
问题背景
想要用Groovy的Closure实现一个通用的静态构建器抽象类WithBuilder,目标是让所有子类都能通过X.with { ... }的流畅语法创建实例。最初尝试的代码存在泛型擦除导致的语法问题,且无法强制子类实现指定的静态方法。
最初的尝试代码:
abstract class WithBuilder<T> { static T with(Closure<T> builder) { Class<T> clazz = T; // 语法无效,泛型类型T无法直接转为Class实例 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); } }
核心问题:
- 泛型类型
T在运行时会被擦除,无法直接通过Class<T> clazz = T获取实际类实例 - 若用
throw new Error('Not implemented')替代,会丢失强制子类实现with方法的约束 - 尝试让子类覆盖父类静态方法时,会收到方法未覆盖父类中的方法警告(Groovy中静态方法不支持继承与覆盖)
期望的使用方式:
import pipeline.Configuration import pipeline.Credentials import pipeline.languages.SupportedLanguages Configuration.with { language SupportedLanguages.Java credentials Credentials.get('user') environments { dev() } }
解决方案
核心思路
Groovy中静态方法属于类本身,不支持继承与覆盖,因此放弃让父类定义抽象静态方法的思路,转而将父类的with(Class<T>, Closure)作为工具方法,由子类实现自身的静态with方法并调用该工具方法。
实现代码
1. 通用父类WithBuilder
abstract class WithBuilder<T> { // 作为工具方法,protected修饰仅允许子类调用 protected static <T> T with(Class<T> clazz, Closure builder) { // 创建实例(要求子类有无参构造方法) T instance = clazz.getDeclaredConstructor().newInstance() // 设置闭包委托为实例,仅使用委托的属性/方法 builder.delegate = instance builder.resolveStrategy = Closure.DELEGATE_ONLY // 执行闭包(无需传递实例,直接通过delegate访问) builder.call() return instance } }
2. 子类实现(以Configuration为例)
class Configuration extends WithBuilder<Configuration> { // 子类实现自己的静态with方法 static Configuration with(Closure builder) { return with(Configuration, builder) } // 实现闭包中需要调用的配置方法 void language(SupportedLanguages lang) { // 处理语言配置逻辑 println "设置语言为: ${lang}" } void credentials(Credentials cred) { // 处理凭证配置逻辑 println "设置凭证为: ${cred.username}" } // 嵌套闭包处理环境配置 void environments(Closure envClosure) { envClosure.delegate = this envClosure.resolveStrategy = Closure.DELEGATE_ONLY envClosure.call() } void dev() { // 开发环境配置逻辑 println "添加开发环境" } } // 配套的辅助类示例 enum SupportedLanguages { Java, Python } class Credentials { String username static Credentials get(String user) { new Credentials(username: user) } }
3. 使用示例
Configuration.with { language SupportedLanguages.Java credentials Credentials.get('admin') environments { dev() } }
补充说明
- 若需要强制子类实现静态
with方法,可以通过代码规范、项目模板或Groovy AST转换工具自动生成该方法 - 嵌套闭包(如
environments)需要单独设置delegate和resolveStrategy,确保内部方法(如dev())能正确映射到实例 - 若子类没有无参构造方法,需要修改父类的实例创建逻辑,改为调用对应参数的构造方法
内容的提问来源于stack exchange,提问作者Solonotix
相关产品推荐
相关产品推荐

