8

I have a Groovy class defined in Vehicles.groovy that contains some inner enums:

public class Vehicles {
  public enum Land {
    BICYCLE,
    CAR,
    TRAIN
  }

  public enum Water {
    SAILBOAT,
    MOTORBOAT
  }

  public enum Air {
    JET,
    HELICOPTER
  }
}

I'd like to reference these enums in a script run.groovy in the same directory as Vehicles.groovy.

Fully qualifying the enum instance works.

import Vehicles
println Vehicles.Land.BICYCLE

or

import static Vehicles.Land
println Vehicles.Land.BICYCLE

or

import Vehicles.Land.*
println Vehicles.Land.BICYCLE

correctly print BICYCLE.

However, I'd like to reference the Land enum without fully qualifying it.

I basically tried every combination of static/non-static, aliased/non-aliased, and star/non-star imports.

import Vehicles.Land or import static Vehicles.Land.* (or import Vehicles.Land as Land) give unable to resolve class errors. This seems weird because they're what one would do in Java (correct me if I'm wrong.)

If I try

import static Vehicles.Land
println Land.BICYCLE

or

import static Vehicles.Land as Land
println Land.BICYCLE

or

import Vehicles.Land.*
println Land.BICYCLE

, I get the error

Caught: groovy.lang.MissingPropertyException: No such property: Land for class: run
groovy.lang.MissingPropertyException: No such property: Land for class: run
        at run.run(run.groovy:2)

Similarly,

import Vehicles.Land.*
println BICYCLE

gives

Caught: groovy.lang.MissingPropertyException: No such property: BICYCLE for class: run
groovy.lang.MissingPropertyException: No such property: BICYCLE for class: run
    at run.run(run.groovy:2)

Adding package declarations to both Vehicles.groovy and run.groovy doesn't seem to help, either.

So...

  • What support does Groovy have for importing inner classes? Why is it it different from Java?
  • How can I get Groovy to allow me to reference non-fully-qualified inner enums?

Note: I'm using Groovy 1.8.6 and Oracle JDK 1.8.0_45.

xlm
  • 6,854
  • 14
  • 53
  • 55
jiangty
  • 311
  • 2
  • 9
  • Have you tried with a version of Groovy released in the past 3 years? [1.8.6 is ancient](http://glaforge.appspot.com/article/groovy-1-8-6-released) – tim_yates Sep 24 '15 at 08:50
  • That's a good point; maybe I should update my version of Groovy? Unfortunately Jenkins `job-dsl-plugin`, which is why I'm writing Groovy, [seems to depend on Groovy 1.8](https://github.com/jenkinsci/job-dsl-plugin/blob/master/gradle.properties#L2). – jiangty Sep 24 '15 at 08:54
  • Looks like the latest only uses 1.8.9 https://github.com/jenkinsci/job-dsl-plugin/blob/master/gradle.properties So I guess you're stuck with having to prefix your enum values – tim_yates Sep 24 '15 at 09:27

2 Answers2

7

Groovy does support import nested classes, including enums. However to access them without full qualification, you'll need to import them in a non-static manner (unlike Java), or explicitly declare them static:

// Explicitly declare Water and Air as static to demonstrate
public class Vehicles {
  public enum Land { BICYCLE, CAR, TRAIN }
  public static enum Water { SAILBOAT, MOTORBOAT }
  public static enum Air { JET, HELICOPTER }
}

// Non-static nested enum needs non-static import (unlike Java)
import Vehicles.Land
println Land.BICYCLE

// Explicitly static nested enum can be static imported
import static Vehicles.Water
println Water.SAILBOAT

// Explicitly static nested enum can also be non-static imported as well!
import Vehicles.Air
println Air.JET

Working example: https://groovyconsole.appspot.com/script/5089946750681088

Unlike Java where enums are implicitly static, it appears that enums in Groovy are not implicitly static, hence why static imports don't work. This is because enums in Groovy aren't actually the same as the ones in Java, they made enhancements. Unfortunately it seems they have forgotten to tell the compiler to also make them implicitly static (at least as of 2.4.4).

My suggestion is to explicitly declare them static (if you can) as it would be keeping with the Groovy notion that valid Java is valid Groovy.

xlm
  • 6,854
  • 14
  • 53
  • 55
5

Have you tried below?

import static Vehicles.Land.*

println BICYCLE

EDIT: is this what you are looking for?

Rao
  • 20,781
  • 11
  • 57
  • 77
  • 3
    As I said in my question, `import static Vehicles.Land.*` throws `org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:` `run.groovy: 1: unable to resolve class Vehicles.Land` – jiangty Sep 24 '15 at 08:41
  • This is tried in IntelliJ IDE and works on https://groovyconsole.appspot.com/script/5096012251136000. – Rao Sep 24 '15 at 08:44
  • those seem to be in the same file? I have them in different files – jiangty Sep 24 '15 at 08:52
  • It works even in the different files. If you are running command line, you need to compile and add to class path of Vehicle. – Rao Sep 24 '15 at 09:25
  • I'm pretty sure Groovy adds files in the same folder to the classpath by default. Note that I provided 3 ways of importing values of `Vehicles.Land`, but `import static Vehicles.Land.*` definitely throws an exception for me. – jiangty Sep 25 '15 at 12:33
  • If possible you may give a try in an IDE like intellij (preferred) or eclipse with groovy plugin to validate the reply. – Rao Sep 25 '15 at 19:06
  • Sorry for not responding for so long, but I suspect that what you're saying works because you're using a newer version of Groovy; see the comments on the question. I just ended up using the fully qualified imports. – jiangty Oct 06 '15 at 01:41
  • I believe that static imports are not the latest feature. – Rao Oct 06 '15 at 12:08
  • 3
    Again, static imports worked fine, but _not_ static importing *. – jiangty Oct 07 '15 at 19:14