Search code examples
groovycastingclosureswith-statementobject-initializers

Creation of an instance with `with` block causes a type issue


I am using Groovy to create a package that I use in ReadyApi.

In a Groovy script test step, I do the following:

class B  {
    String value
    boolean isSomething
}

class A {
    String name
    B propB

    public A() {
        this.name = "Maydan"
    }
}

def x = (A) new A().with  { propB = new B(value: "Abc", isSomething: true) }

And I get the following error:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'B@6c218cea' with class 'B' to class 'A' error at line: 15

Does someone know why? It doesn't make any sense to me.

Kind regards.

PS: I would like to create an instance of class A (by using its parameterless constructor) and setting its field propB in a single statement


Solution

  • You need to return your A object from the .with closure. You may do it like that:

    def x = (A) new A().with  { propB = new B(value: "Abc", isSomething: true); return it}
    

    but to me personally it looks a little bit odd. I would do it like that:

    def x = new A(propB: new B(value: "Abc", isSomething: true))
    

    The same effect, but more compact and readable. It doesn't require to change your A and B definitions, this "map constructor" works out of the box in Groovy, it will call your parameterless constructor and then assigns the necessary fields (propB in your case).