tags:

views:

44

answers:

2

I seem unable to use a Closure as a parameter to a superclass constructor when it is specified inline.

class Base {

  def c

  Base(c) {
    this.c = c
  }

  void callMyClosure() {
    c()
  }
}

class Upper extends Base {
  Upper() {
    super( { println 'called' } )
  }
}

u = new Upper()
u.callMyClosure()

The compilation fails with the message Constructor call must be the first statement in a constructor..

I realize this a somewhat strange use-case, and I can design around it for the time being. But I'm interested, is this is to be expected? Or have I got the syntax incorrect?

A: 

It might be confusing a closure and a block...can you try

super( { -> println 'called' } )
tim_yates
Gives the same result I'm afraid. Good idea though!
David Padbury
+1  A: 

I think that the problem is related to the fact that Groovy turns the constructor into something different while trying to compile it as a Java class. Maybe the closure definition is expanded before the call to super generating that error.

A workaround is to define the closure outside the constructor itself:

class Base {
  def c

  Base(c) {this.c = c}


  void callMyClosure() {
    c()
  }
}

class Upper extends Base {
  static cc = {println 'called'}

  Upper() {
    super(cc)
  }
}

u = new Upper()
u.callMyClosure()

It's not so nice but at least it works.. another way could be to define the closure by using a normal new Closure(...) syntax

Jack
That's what I was expecting, but just couldn't find any documentation. I also found the same behavior using a Map that was initialized there.
David Padbury
Out of interest, what's the new Closure syntax? The Closure class itself is abstract.
David Padbury
I did some tries to find out that weird syntax (instantiate the closure before using it into the constructor).. from what I understood it seems that it's abstract because you usually subclass it and implement the `doCall` method that is the effective body of the closure
Jack
Yeah - it's certainly interesting to read about. Thanks for your input!
David Padbury