Groovy 2.4.11中this.@foo赋值触发setFoo方法报错问询
Let's break down what's happening here and how to fix it.
First, here's your problematic code for clear reference:
enum EnumClass { a, b } class Some { Foo foo Some() { EnumClass.with{ this.@foo = new Foo( a ) } } Some setFoo( String _foo ) { /* ... existing logic ... */ } }
When you call new Some(), you hit this runtime error:
groovy.lang.MissingMethodException: No signature of method: MyClass.setFoo() is applicable for argument types: (Foo) values: [Foo$12345] ...
Why This Happens
In Groovy 2.4.11, there's a parsing ambiguity when using the direct field access syntax (this.@field) inside a closure (like the one passed to EnumClass.with). The compiler fails to properly recognize the @ marker that signals direct field assignment, and instead falls back to Groovy's default property access behavior—meaning it tries to call the corresponding setter method (setFoo) instead of assigning the field directly. Since your setFoo expects a String but you're passing a Foo instance, you get the missing method exception.
Fixes You Can Apply
1. Capture the Outer this Reference Before the Closure
The simplest workaround is to store a reference to the current Some instance outside the closure, then use that reference for the direct field assignment:
Some() { def self = this EnumClass.with{ self.@foo = new Foo( a ) } }
This avoids the closure context interfering with how Groovy parses the field access syntax.
2. Use MetaProgramming to Set the Field Directly
You can bypass Groovy's property resolution entirely by using the meta class to set the field directly:
Some() { EnumClass.with{ this.metaClass.setProperty(this, 'foo', new Foo( a )) } }
This tells Groovy explicitly to target the underlying field instead of looking for a setter.
3. Add a Setter Overload (If Business Logic Allows)
If your use case permits, you can add an overload of setFoo that accepts a Foo instance, which will be called instead of the String version when you assign the property:
Some setFoo( Foo _foo ) { this.@foo = _foo return this } Some setFoo( String _foo ) { // Keep your existing string-handling logic here return this }
Note: This only works if you're okay with having a setter that accepts Foo—if that doesn't fit your design, stick with the first two options.
A Quick Note on Versioning
This parsing issue appears to be specific to Groovy 2.4.x; later versions (2.5+) have fixed this ambiguity around direct field access in closures. But if you're stuck on 2.4.11 for compatibility reasons, any of the above fixes should resolve your error.
内容的提问来源于stack exchange,提问作者Andreas Covidiot

