Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-7246

Access modifiers behave differently in Groovy when compared to Java.

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.3.9
    • 2.3.9
    • None
    • 64-bit Windows 7

    Description

      I know there's already been several JIRA tickets that have been created concerning how private fields and methods aren't really private in Groovy.

      See Also: GROOVY-3010

      But it seems like Groovy doesn't respect the access restrictions of any of the access modifiers. Last year I did a blog post on Java's access modifiers and recently I did the same experiment but with Groovy this time. I've listed below all the classes that I used. I only changed the access modifiers for the name field and speak method of the Earthling class.

      Earthling.groovy
      package Earth;
      
      // access modifiers will be changed for this class
      public class Earthling {
         public String name = "Bob";
       
         public void speak() {
            System.out.println("Hello.");
         }
      }
      
      Man.groovy
      package Earth;
      
      // subclass, same package
      public class Man extends Earthling {
         public Man() {
            System.out.println("name = " + name);
            speak();
         }
       
         public static void main(String[] args) {
            new Man();
         }
      }
      
      Dog.groovy
      package Earth;
      
      // non-subclass, same package 
      public class Dog {
         public Dog() {
            Earthling earthling = new Earthling();
            System.out.println("earthling.name = " + earthling.name);
            earthling.speak();
         }
       
         public static void main(String[] args) {
            new Dog();
         }
      }
      
      Explorer.groovy
      package Mars;
       
      import Earth.Earthling;
      
      // subclass, different package
      public class Explorer extends Earthling {
         public Explorer() {
            System.out.println("name = " + name);
            speak();
         }
       
         public static void main(String[] args) {
            new Explorer();
         }
      }
      
      Martian.groovy
      package Mars;
       
      import Earth.Earthling;
      
      // non-subclass, different package
      public class Martian {
         public Martian() {
            Earthling earthling = new Earthling();
            System.out.println("earthling.name = " + earthling.name);
            earthling.speak();
         }
       
         public static void main(String[] args) {
            new Martian();
         }
      }
      

      When I did this little experiment in Java, I got the following results. The cells marked with 'J' indicates when I was able to access Earthling's name field and speak method.

        public protected (no modifier) private
      Subclass, Same Package J J J  
      Non-Subclass, Same Package J J J  
      Subclass, Different Package J J    
      Non-Subclass, Different Package J      

      When I did the same thing in Groovy, however, I got much different results. Note I've marked the cells with 'G' this time.

        public protected (no modifier) private
      Subclass, Same Package G G G throws exception
      Non-Subclass, Same Package G G G G
      Subclass, Different Package G G G throws exception
      Non-Subclass, Different Package G G G G

      You'll notice that pretty much every class can access everything. The only issues occur when you use the private access modifier and you try to access the field or method from a subclass. But instead of throwing a compiler error, like Java does, Groovy throws runtime exceptions. Specifically,

      groovy.lang.MissingPropertyException: No such property: name
      

      And if you comment out the statement that references the name field...

      Man.groovy
      package Earth;
      
      // subclass, same package
      public class Man extends Earthling {
         public Man() {
            // System.out.println("name = " + name);
            speak();
         }
       
         public static void main(String[] args) {
            new Man();
         }
      }
      

      ...you'll get a different exception.

      groovy.lang.MissingMethodException: No signature of method: Earth.Man.speak
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            tygerpatch Todd Gerspacher
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: