MissingMethodException when calling method inside another - groovy

I am trying to call a method inside another and I am getting a MissingMethodException. My code looks something like this:
class Foo {
static def bar {
//do stuff
return something
}
static def baz { myVar=false ->
def something = bar()
//do stuff w/something
}
}
Foo.baz()
and this is the error I get: Caught: groovy.lang.MissingMethodException: No signature of method: Foo$__clinit__closure6.bar() is applicable for argument types: () values: []
I found that I can fix this error if I define baz like this instead:
static def baz { myVar=false ->
def something = this.bar()
//do stuff w/something
}
but if I do that, my IDE tells me that this is an Unnecessary qualified reference.
What's going on here?

That syntax in your snippet is wrong. Either you wanted static def bar = {} or static def bar() {}.
If you wanted bar to be a method, then there is no error:
class Foo {
static bar() { 'something' }
static baz = { myVar=false ->
def something = bar()
return something + "!"
}
}
assert Foo.baz() == "something!"
If you want bar to be a closure (i.e. bar = {}) then to invoke bar from baz you need to put the class name first:
class Foo {
static bar = { 'something' }
static baz = { myVar=false ->
def something = Foo.bar()
return something + "!"
}
}
assert Foo.baz() == "something!"

Related

Idiomatic means of choosing class constructor in groovy

I have a class like this:
in foo.groovy
class Foo {
String thing
Integer other
Foo(String thing) {
this.thing = thing
}
Foo(Integer other) {
this.other = other
}
}
return Foo.class
Now I would like to invoke these constructors. What I am doing is:
Other.groovy
def foo = evaluate(new File(ClassLoader.getSystemResource('foo.groovy').file)).newInstance(10)
def foo2 = evaluate(new File(ClassLoader.getSystemResource('foo.groovy').file)).newInstance("thing")
But this doesn't seem like the correct way of doing it. Ideally I would like to actually name the file Foo.groovy but then I get an error because it automatically declares the class for me. Basically, I want it to work like a classic Java class
Maybe I'm missing something here, but:
class Foo {
String thing
Integer other
Foo(String thing) {
this.thing = thing
}
Foo(Integer other) {
this.other = other
}
}
def x = new Foo(10)
assert x.other == 10 // true
def y = new Foo("foo")
assert y​​​​.thing​ == "foo"​​ // true
What are you trying to accomplish here other than that?
Edit: Try it here.

Is there a way to mimic map like access (using brackets) to get method on an arbitrary object

Is there a way in groovy where I can use brackets to access the get function like with maps? Something like this:
class Foo<V> {
String bar = "Bar:"
V get(Object lal) {
return bar + lal
}
}
def f = new Foo()
println(f["xxx"])
PS I would like to avoid extending the whole Map interface.
It works this way:
class Foo {
String bar = "Bar:"
def getAt(String lal) {
return bar + lal
}
def getAt(int i) {
return bar + i
}
}
def f = new Foo()
println(f["xxx"])
println(f[0])
You need to pass concrete object class.

Groovy - #DelegatesTo(strategy=Closure.DELEGATE_ONLY, ...) unexpected behavior

In this code, the assertion is failing:
class Foo {
def foo() { 'foo' }
}
def foo() { 'foo2' }
def bar(#DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=Foo) Closure c) {
c.delegate = new Foo()
c()
}
assert bar { foo() } == 'foo'
I expected the assertion to pass because the strategy is specified as Closure.DELEGATE_ONLY, and so it should only be trying to resolve foo() using the delegate which is new Foo(), otherwise throw an exception. I didn't think I'd have to specify the strategy explicitly again in the body of the function with c.resolveStrategy = Closure.DELEGATE_ONLY. That just seems verbose. Is this expected behavior?

Groovy closures, def vs typed return value

In the Groovy console, version 2.2.1:
Why does this work?
class C {
def foo = { "foo" }
def bar = { foo() }
}
new C().bar()
but this fails?
class C {
String foo = { "foo" }
String bar = { foo() }
}
new C().bar()
The above was answered by tim_yates but I have something somewhat related that doesn't seem like it's worth creating a new question for (not sure of the etiquette). When I make them static it also fails when I call bar(). Why does the bar closure not capture foo?
class C {
static foo = { "foo" }
static bar = { foo() }
}
C.foo() //works
C.bar() //fails
Because neither { "foo" } or { foo() } are Strings?
They are Closure<String>
Try:
class C {
Closure<String> foo = { "foo" }
Closure<String> bar = { foo() }
}
new C().bar()

Coercion befuddlement in Groovy

Why does the following
class Test {
#Test
void go() {
def foo1 = new MockFoo1() as Foo
def foo2 = new MockFoo2() as Foo
}
interface Foo {}
class MockFoo1 {}
class MockFoo2 {}
}
Result in a java.lang.IllegalArgumentException: argument type mismatch on the foo2 coercion?
This only happens if I coerce 2 objects of 2 different types to the same interface during a single path of execution. The groovy approved way of using closures or maps to achieve this kind of duck typing works fine.
Any light shed appreciated.
It's a bug with the ProxyGenerator adapterCache. As a workaround, you can also use some Groovy trickery to make this work:
interface Foo {
static a = {
[MockFoo1, MockFoo2].each {
it.metaClass.asType = { Class klazz ->
try {
DefaultGroovyMethods.asType(delegate, klazz)
} catch (e) {
def cache = ProxyGenerator.INSTANCE.#adapterCache.#cache
cache.each { k, v ->
cache.remove(k)
}
DefaultGroovyMethods.asType(delegate, klazz)
}
}
}
}()
}
class MockFoo1 {}
class MockFoo2 {}
def a = new MockFoo1() as Foo
def b = new MockFoo2() as Foo
assert a instanceof Foo
assert b instanceof Foo
Hope this helps!

Resources