tags:

views:

225

answers:

1

In Groovy, I have a parent class and a child class where the parent class's constructor tries setting the value of a field of the parent class using a closure as in the following code:

try {
  def x = new ChildClass()
} catch (ex) {
  ex.printStackTrace(System.err)
}

class ParentClass {
  private values = []

  ParentClass(columnCount) {
    columnCount.times { values.add('') }
  }
}

class ChildClass extends ParentClass {
  ChildClass() {
    super(20)
  }
}

However, when I run this code I get a groovy.lang.MissingPropertyException with the message "No such property: values for class: ChildClass". However, if I change the parent class's constructor to not use the closure with the times method as in this example:

try {
  def x = new ChildClass()
} catch (ex) {
  ex.printStackTrace(System.err)
}

class ParentClass {
  private values = []

  ParentClass(columnCount) {
    def i
    for (i = 0; i < columnCount; i++) {
      values.add('')
    }
  }
}

class ChildClass extends ParentClass {
  ChildClass() {
    super(20)
  }
}

It works. Can someone explain this behavior to me? I don't understand why Groovy thinks the values field is a property of the child class. I am using Groovy version "Groovy Version: 1.6.3 JVM: 1.5.0_18".

A: 

This is a known bug in the current version of groovy and is targeted for being fixed in groovy 2.0. See GROOVY-3073.

It's happening because of a scoping bug in the metaclass where the closure in the first example can't see the private class level variable.

One potential fix that gets around the issue for this situation is to declare a local alias variable in the superclass, this gets around the scoping issue in the closure. Change the constructor to this:

  ParentClass(columnCount) {
     def valueAlias = values
     columnCount.times { valueAlias.add('') }
  }
Ted Naleid