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!
Related
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 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.
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!"
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()
Given:
class FruitBasket {
int apples = 0
int oranges = 0
}
I need to pick out apples from each FruitBasket. The work need to be done in processFruit:
def processFruit(list, picker) {
list.each {
println "processing " + picker(it)
}
}
def processAll() {
List fruitList = [
new FruitBasket("apples": 2, "oranges": 4),
new FruitBasket("apples": 3, "oranges": 5)
]
processFruit(fruitList, applePicker)
}
def applePicker(FruitBasket f) {
return f.getApples()
}
but it is complaining # runtime that
No such property: applePicker for class: FooTest
possibly a problem with the closures FruitBasket arg...
In that code, applePicker is a method, not a closure.
You can either use a method handle to pass the method as a parameter like so:
processFruit(fruitList, this.&applePicker)
Or change it to an actual closure:
def applePicker = { FruitBasket f -> return f.getApples() }
You are passing applePicker to processFruit, but it is a method. You can only pass closures this way. Redefine applePicker as a closure like so:
applePicker = { FruitBasket f ->
return f.getApples()
}
Or convert the method to a closure when processFruit is called:
processFruit(fruitList, this.&applePicker)