访问groovy getter而不是遵从@Delegate

访问groovy getter而不是遵从@Delegate,groovy,delegates,annotations,javabeans,abstract-syntax-tree,Groovy,Delegates,Annotations,Javabeans,Abstract Syntax Tree,给定一段代码: class Foo { @Delegate Map data Foo(data) { this.data = data } def getBar() { "Bar" } } new Foo([:]).bar // null new Foo([:]).getBar() // "Bar" 代理似乎在转换为对getter的调用之前拦截了对.bar的调用。这有什么关系吗?我希望有一个映射的委托,但仍然能够使用调用站点上的cleaner.bar来引用属性。您在这里得到的

给定一段代码:

class Foo {
  @Delegate Map data

  Foo(data) { this.data = data }

  def getBar() { "Bar" }
}

new Foo([:]).bar // null
new Foo([:]).getBar() // "Bar"

代理似乎在转换为对getter的调用之前拦截了对
.bar
的调用。这有什么关系吗?我希望有一个映射的委托,但仍然能够使用调用站点上的cleaner
.bar
来引用属性。

您在这里得到的比您实际需要的更多(映射中的属性处理——至少这是我的猜测)。除非有人找到解决方法(
@Delegate
上的
排除
对我不起作用),否则您最好只使用expando:

@groovy.transform.InheritConstructors
class Foo extends Expando {
    def getBar() { "Bar" }
}

def f = new Foo(baz:'baz')
assert f.foo==null
assert f.bar=="Bar"
assert f.getBar()=="Bar"
f.foo="F00"
assert f.foo=="F00"
assert f.baz=="baz"

好的,这是一个笨拙的解决方案,但是将构造函数更改为从给定的映射生成一个defaultMap,以调用getter作为回退似乎可以满足我的需要

class Foo {
  @Delegate Map data

  Foo(data) { this.data = data.withDefault { "get${it.capitalize()}"() } }

  def getBar() { "got bar" }
}

这样做的缺点是,当地图有一个带有“bar”键的条目时,仍然首选地图。仍然希望有人有更好的解决方案。

有趣的解决方案,我想我更喜欢它,而不是默认的
。由于我正在包装一个现有的映射,有没有一种简单的方法可以从映射实例填充expando?啊,是的,只是
newfoo(myMap)
似乎可以通过继承构造函数转换来完成。