groovy 在方法中设置闭包的委托会导致SO

qeeaahzv  于 4个月前  发布在  其他
关注(0)|答案(2)|浏览(44)

使用code with builder

Closure getObject = { String oType ->
  return {
    type oType
    format 'int32'
  }
}

def yaml = new YamlBuilder()
yaml{
  string 'value'
  object1{
    Closure type = getObject 'integer'
    type.delegate = delegate
    type()
  }
  object2{
    Closure type = getObject 'long'
    type.delegate = delegate
    type()
  }
}

println yaml.toString()

字符串
代码按预期工作并生成正确的yaml。
现在我想删除重复的代码行,并引入inflate()方法:

def inflate( Closure closure, delegate ) {
  closure.delegate = delegate
  closure.resolveStrategy = Closure.DELEGATE_FIRST
  closure()
}


这样我的DSL就更紧凑了

yaml{
  string 'value'
  object1{
    inflate getObject( 'integer' ), delegate
  }
  object2{
    inflate getObject( 'long' ), delegate
  }
}


这导致了SOE:

java.lang.StackOverflowError
    at Script1$_run_closure1$_closure3.doCall(Script1.groovy:5)
    at Script1$_run_closure1$_closure3.doCall(Script1.groovy)


我错过了什么?
脚本可以用on appSpot播放

baubqpgj

baubqpgj1#

不是100%确定是怎么回事,但这似乎有效

Closure getObject = { String oType, del ->
  { ->
    type oType
    format 'int32'
  }.tap { 
      it.delegate = del
      it.resolveStrategy = Closure.DELEGATE_FIRST
  }
}

def yaml = new YamlBuilder()
yaml{
  string 'value'
  object1{
    getObject('integer', delegate)()
  }
  object2{
    getObject('long', delegate)()
  }
}

字符串

ss2ws0br

ss2ws0br2#

事实证明,应该使用闭包而不是方法。
在这种情况下,闭包嵌套和重用不再是问题:

import groovy.yaml.YamlBuilder

Closure inflate = { Closure closure, del ->
  closure.delegate = del
  closure()
}

Closure getObject = { String oType ->
  return {
    type oType
    format 'int32'
  }
}

Closure getNestedObject = {
  return {
    type 'object'
    nested{
      inflate getObject( 'nested' ), delegate     
    }
  }
}

def yaml = new YamlBuilder()

yaml{
  string 'value'
  object1{
    inflate getObject( 'integer' ), delegate
  }
  object2{
    inflate getNestedObject(), delegate    
  }
}

println yaml.toString()

字符串
指纹

---
object1:
  type: "integer"
  format: "int32"
object2:
  type: "object"
  nested:
    type: "nested"
    format: "int32"


可运行代码is here

相关问题