tags:

views:

130

answers:

2

Just started learning Groovy, got the PragProg book "Programming Groovy" and had a problem compiling one of the sample scripts:

class GCar2 {
  final miles = 0

  def getMiles() {
    println "getMiles called"
    miles
  }

  def drive(dist) {
    if (dist > 0) {
      miles += dist
    }
  }
}

def car = new GCar2()

println "Miles: $car.miles"
println 'Driving'
car.drive(10)
println "Miles: $car.miles"

try {
  print 'Can I see the miles? '
  car.miles = 12
} catch (groovy.lang.ReadOnlyPropertyException ex) {
  println ex.message

GroovyCar2.groovy: 20: cannnot access final field or property outside of constructor.
 @ line 20, column 35.
     def drive(dist) { if (dist > 0) miles += dist }
                                     ^

Groovy versions prior to 1.7 do not give an error. I looked through whatever documentation I could find and did not see the issue discussed. What is going on here?

Aaron

+1  A: 

I don't know much about Groovy 1.7, but it looks like a bug in earlier versions which has now been fixed - if a variable is final, you shouldn't be able to assign to it outside the constructor (or its declaration). If you can, what's the point of making it final?

I doubt that it'll stop you from reading it outside the constructor though...

Jon Skeet
In 'Programming Groovy', Subramanian actually touts the use of final in the code example:"If you want a property to be read-only, then declare it final. This is not defining a final field but a read-only property -- you can change the property from within instance methods of the defining class, but not from outside."His example was supposed to show the use of 'final' in that context, but clearly no longer works.While the use of 'final' post 1.7 is intuitive to Java programmers, I'm not so sure it was really a bug but rather an implementation that some found confusing.
Aaron L. Carlow
@Aaron: Groovy in Action states: "When the final keyword is used with a property declaration, the property will only be readable (no setter method is created and the backing field is final)." Of course, I'm somewhat biased :)
Jon Skeet
A biased informed answer is better than its unbiased converse :) Any idea why the behavior Subramaniam talks about persisted from Groovy-1.0 through Groovy 1.6.8? If it really was a bug, it seems hard to believe it would have persisted for so long. Wouldn't some existing code break as a result of this change?
Aaron L. Carlow
@Aaron: I don't really know, to be honest. I suspect that what we wrote in Groovy in Action was the *intended* behaviour all along. It certainly makes *sense* as the intended behaviour (IMO). It does seem odd that it's taken so long to fix.
Jon Skeet
+2  A: 

You shouldn't be able to assign to a final variable in a normal method. It was a bug in groovy, fixed in 1.7.

ataylor