The effect of modules on 'protected'

Adding modules to the Java language has an interesting interaction with protected accessibility.

First, consider how protected accessibility is described in JLS 6.6.2: "A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object." The "responsible for implementation" phrase is a piece of morality which translates to the accessing code being in a subtype of the type which declares the protected member. Then, ignoring private, there is a total ordering of accessibility levels:

  public
|
protected
// other pkg if subtype
|
package

For module accessibility, the JLS will say something like: "A module-private member or constructor of an object can be accessed from outside the package in which it is declared by code that belongs to the same module." There will then be two accessibility levels greater than package and less than public:
               public
___________|____________
| |
| |
protected module
// other pkg if subtype // other pkg if same module
| |
|___________ ____________|
|
package

Is a total ordering possible? Consider the accessibility of a protected member:


  • same package, or
  • subtype in different package

When protected was invented, the types "responsible for implementation" of an object could be as far away as a different package. With modules, they could be as far away as a different module. This gives two options for which subtypes can access a protected member:


  • subtype in different package in same module
  • subtype in different package in any module

Suppose we decided, on a moral basis, that a single module is the unit "responsible for implementation". Then, protected members should be accessible to subtypes only in the same module. This induces a total ordering:

  public
|
module
// other pkg if same module
|
protected
// other pkg if subtype and in same module
|
package

But this decision is not very pragmatic. It means two packages where one has a protected member and one has an accessing subtype cannot be factored into two modules. We have no statistics on the popularity of putting related packages in different JAR files, but it seems a reasonable thing to do. Making protected strongly respect a module boundary seems likely to cause pain when moving types into modules. Elsewhere, we have gone to some lengths to ensure that publicly accessible types remain publicly accessible if they're thrown into modules. I conclude that multiple modules can jointly be "responsible for implementation", and that the appropriate interaction of protected and modules is for protected members to be accessible to subtypes in different packages even in different modules.

What about the accessibility ordering now?


  • For module to be more accessible than protected, the accessors of a protected member would have to be a subset of the accessors of a module member. This is not true - an accessor of a protected member can be in a different module, hence outside the set of accessors of a module member.
  • For protected to be more accessible than module, the accessors of a module member would have to a subset of the accessors of a protected member. This is not true - an accessor of a module member can be any type in the module, not just certain subtypes like the set of accessors of a protected member in that module.

So we're stuck with a partial ordering, albeit with a better understanding of what protected means w.r.t. modules:

               public
___________|____________
| |
| |
protected module
// other pkg if subtype // other pkg if same module
| |
|___________ ____________|
|
package

Finally, protected is really a meta-modifier - it modifies the package modifier (spelled '' of course) to add accessibility from subtypes. It's not unreasonable for protected to modify module too, such that module protected means accessible from:


  • same module, or
  • subtype in different (package or) module

giving the ordering:
              public
|
module protected
// other pkg if same module
// other module if subtype
___________|____________
| |
| |
protected module
// other pkg if subtype // other pkg if same module
| |
|___________ ____________|
|
package

The bane of protected is the obscure relationship between the type declaring the protected member and the qualifying type of the reference to the member, enforced during compilation and verification. But this relationship is independent of whether the accessing subtype is in a different package or a different module, so it is not a prima facie reason against module protected. Whether module protected is worthwhile is an open question - it can't be removed if it's somehow 'wrong', the classfile format would have to be updated, tools would need to parse it, etc, etc. module protected would however be an interesting counterpart to Peter Kriens' multi-module accessibility level, which one might denote module exported. Watch this space.

Comments:

Really interesting - I hadn't even given this any thought! I think I'll definitely need a nice matrix to sum up the new access modifiers and how they apply across modules once the decisions are all final :)

Posted by The real Mr. Funk on May 22, 2008 at 01:58 PM PDT #

Bring back private protected! :)

Posted by Tom Hawtin on May 22, 2008 at 11:31 PM PDT #

2 cents

I see super-package/module and subclassing-contract scopes as orthogonal. So I don't see a need for an ordering.

I would say that the 'problem' is with protected scope. It blurs two distinct distinct concepts: package 'friendliness' and subclassing. Not that that could/should be fixed but not sure the pattern needs to be continued.

As well, I suppose allowing module protected has some logic from a scoping perspective (although in practice it would seem yucky, I would still 'vote' for it).

Digressing, I see module scope as addressing part of the problem with the lack of a 'friend' concept in Java.

Public ends up with a very poor semantic. Methods have to be public if they are:
a) truly part of the classes API/contract
b) 'module' scope
c) part of another 'friendly' relation (e.g. used by inversion of control or management sub-system).
d) designer default, since they end up having to make lots of other methods public anyways.
e) ...

This makes it difficult to look at set of classes and figure out 'how am I supposed to use it?' and difficult to use the sub-system 'correctly'.

Personally I have been debating whether module is really 'just' an annotation. That would make (especially compile-time) enforcement more difficult, but would allow more general specification (@Scope(ioc)) and could be tied into aspecty mechanisms and Javadoc.

That said, often a specific solution (module?) can be better than a general (@Scope?). E.g. '+' for String concatenation instead of general operator overloading.

Posted by Bryn Rahm on May 29, 2008 at 02:43 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

Alex Buckley is the Specification Lead for the Java language and JVM at Oracle.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Feeds