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

Groovy实现类Shell管道式调用及闭包值修改的优化方案咨询

问题

想要实现类似Shell管道的调用方式,满足以下需求:

  • 调用foo( 'abc' )直接返回默认结果'abc ~> 123'
  • 调用foo( 'abc' ).bar( 'efg' )返回带额外参数的结果'efg : abc ~> 123'

先后进行了三次尝试,但都存在问题:

第一次尝试

def foo ( String aStr ) {
    String constant = '123'
    String result = "${aStr} ~> ${constant}"

    [
        bar : { String bStr -> result = "${bStr} : ${result}"; return result }
    ]
    println result
}

foo( 'abc' )                    // abc ~> 123
foo( 'abc' ).bar( 'efg' )       // java.lang.NullPointerException: Cannot invoke method bar() on null object

直接调用foo('abc')正常,但调用foo('abc').bar('efg')会抛出空指针异常——因为foo最后执行println后返回null,无法调用bar方法。

第二次尝试

def foo ( String aStr ) {
    String constant = '123'
    String result = "${aStr} ~> ${constant}"
    
    [
        bar     : { String bStr -> result = "${bStr} : ${result}"; println "${result}" } ,
        default : { println result }
    ]
}

foo( 'abc' ).bar( 'efg' )          // efg : abc ~> 123
foo( 'abc' ).default()             // abc ~> 123

实现了两种调用,但需要额外调用default()才能获取默认结果,且结果只能通过println输出,无法直接返回字符串用于后续操作。

第三次尝试

def foo ( String aStr ) {
    String constant = '123'
    String result = "${aStr} ~> ${constant}"

    [
        bar : { String bStr = '' -> result = "${bStr ? "${bStr} : " : ''}${result}"; return result }
    ]
}

foo( 'abc' )                 // [bar:ConsoleScript22$_foo_closure1@5e7667fd]
foo( 'abc' ).bar()           // abc ~> 123
foo( 'abc' ).bar( 'efg' )    // efg : abc ~> 123

bar支持无参调用获取默认结果,但直接调用foo(..)返回的是Map对象,而非预期的字符串结果。

优化实现方案

可以利用Groovy的Expando类实现,它允许动态添加方法,同时重写toString()方法,让直接调用foo()时返回预期字符串,调用bar()时返回处理后的结果:

def foo(String aStr) {
    String constant = '123'
    String baseResult = "${aStr} ~> ${constant}"
    
    def expando = new Expando()
    
    // 实现bar方法
    expando.bar = { String bStr ->
        return "${bStr} : ${baseResult}"
    }
    
    // 重写toString,直接调用foo时返回默认结果
    expando.toString = {
        return baseResult
    }
    
    return expando
}

// 测试调用
println foo('abc')                  // abc ~> 123
println foo('abc').bar('efg')       // efg : abc ~> 123

方案优势

  1. 完全满足需求:直接调用foo('abc')返回默认字符串,调用foo('abc').bar('efg')返回带参数的结果
  2. 结果可直接作为字符串使用,无需额外调用方法或依赖println输出
  3. 逻辑清晰,没有冗余代码,符合Groovy动态特性的最佳实践

如果更倾向于结构化实现,也可以用自定义类完成,逻辑类似但更严谨:

class FooResult {
    private String baseResult
    
    FooResult(String aStr) {
        this.baseResult = "${aStr} ~> 123"
    }
    
    String bar(String bStr) {
        return "${bStr} : ${baseResult}"
    }
    
    @Override
    String toString() {
        return baseResult
    }
}

def foo(String aStr) {
    return new FooResult(aStr)
}

// 测试调用
println foo('abc')                  // abc ~> 123
println foo('abc').bar('efg')       // efg : abc ~> 123

内容的提问来源于stack exchange,提问作者Marslo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 22:35:36