groovytypesinstantiationread-eval-print-loopgroovysh

Strange behavior using def in groovy's repl (groovysh)


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


Solution

  • 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