2

Problem Summary

This morning I was using groovysh to test a closure but in the process of doing so I experience unexpected behavior I defined a class in groovysh then instantiated an object from that class as follows

groovy:000> class Student {
groovy:001> def firstName
groovy:002> def lastName
groovy:003> }
===> true
groovy:000> def chris = new Student()
===> Student@52d239ba

I then tried to set the firstName attribute using an implicit setter method as follows:

groovy:000> chris.setFirstName("chris")

And received the following error

Unknown property: chris

I then tried to instantiate a new object without def it executed successfully

groovy:000> jen = new Student()
===> Student@c1bd0be
groovy:000> jen.setFirstName("Jenifer")
===> null

Not understanding why this was happening I then created an executable groovy file (as seen below)

class Student {
    def firstName
    def lastName
}

def chris = new Student()
chris.setFirstName("Christopher")
println chris


john = new Student()
john.setFirstName("Jonathan")
println john

I then executed the script and received the following output

Student@6ab778a
Student@1dac5ef

I found this very odd because the script threw an exception in groovysh but executed successfully as a standalone file.

My groovy -v is Groovy Version: 2.6.0-alpha-2 JVM: 1.8.0_111 Vendor: Oracle Corporation OS: Windows 10, and I was running groovysh in Powershell with Administrator privileges.

I did a few minutes of research to better understand this anomaly but because the search terms (groovy, def, groovysh, repl, instantiation, exception, etc) are so common I was not able to find anything that explicitly addressed this behavior.

Any explanation would be greatly appreciated

Chris Maggiulli
  • 3,375
  • 26
  • 39

1 Answers1

2

This is described on the groovysh documentation page:

Shell variables are all untyped (i.e. no def or other type information).

This will set a shell variable:

foo = "bar"

But, this will evaluate a local variable and will not be saved to the shell’s >environment:

def foo = "bar"

You can enable interpreter mode to change the behavior (type this in the groovysh console):

:set interpreterMode true
Community
  • 1
  • 1
ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • Thank you very much for the reply. If I'm reading this correctly, a variable instantiated with def will not be accessible further down in the shell, but a class initialized with def will be? Is there a reason they did this? – Chris Maggiulli Sep 01 '18 at 19:00
  • @ChrisMaggiulli I'm not sure I understand correctly. I suspect that this is because of how the context and evaluation of scripts is processed. I haven't seen the source of this, but I would assume that each command makes its own script and the code goes into the `run` method, which would exclude other local variables (and the shell would make exceptions for variables declared without `def` or specific data types). – ernest_k Sep 01 '18 at 19:07
  • Awesome, thank you very much for sharing your knowledge me with. – Chris Maggiulli Sep 01 '18 at 19:08