You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在子类中继承静态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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:53:05