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.
package Earth; // access modifiers will be changed for this class public class Earthling { public String name = "Bob"; public void speak() { System.out.println("Hello."); } }
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(); } }
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(); } }
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(); } }
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...
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