Accessibility Rules for Members – Java Module System

Accessibility Rules for Members

Table 19.1 summarizes the accessibility rules for members of a public class A contained in a package pkg1 of module M. Note that class A is public so that it satisfies one of the three conditions discussed earlier for accessibility of a type from another module.

Table 19.1 Module Accessibility Rules

Access modifier for members in public class A inside package pkg1 of module MInside module MInside module N
publicAccessible in all packages in module MAccessible in all packages in module N, if and only if module N requires module M and module M exports pkg1
protectedAccessible in package pkg1, and accessible only by subclasses of class A in other packages in module MAccessible by subclasses of class A in all packages in module N, if and only if module N requires module M and module M exports pkg1
package-privateOnly accessible in package pkg1Not accessible
privateOnly accessible in class ANot accessible

In Table 19.1, the middle column shows how the members of public class A are accessible inside module M. Accessibility rules for members that are applied before modules are now only applicable for accessing members inside a module.

In module N, the public and the protected members of public class A are accessible if and only if class A is accessible in module N. In order for class A to be accessible in module N, the conditions for accessibility of types must be satisfied: Module N requires module M, module M exports package pkg1, and class A in package pkg1 is public. Not surprisingly, private and package-private members of public class A are not accessible in module N.

Implied Module Dependencies

As an example of refactoring modules, we will refactor the seller module in Figure 19.3(b). We decide to move the package com.abc.factory and its subpackage com.abc.factory.test to a new module called factory. The effects of this factoring are illustrated in Figure 19.5. Now both client and seller require factory, as can be seen from their module declarations in Figure 19.5(d) and (e). The package com.abc.factory is now exported by the module factory in Figure 19.5(f). Apart from fixing the module declarations and moving the relevant packages from seller to factory, no other changes are necessary.

Figure 19.5 Module Declarations and Module Graph

The module graph in Figure 19.5 shows the dependencies between the modules after refactoring. Note that there are two paths from client to factory in the module graph. One might be tempted to think that since client requires seller and seller requires factory, then client requires factory transitively, and we could omit the requires directive on factory in client. However, the compiler will diligently flag an error. Dependencies specified by the requires directive are not transitive.

The requires transitive Directive

Implied dependencies can be created by the requires transitive directive. This is illustrated in Figure 19.6. If it is the case that all modules that require seller will also require factory, we can omit the requires directive on factory in client and use a requires transitive directive in seller. In Figure 19.6, client no longer requires factory, but seller specifies factory in a requires transitive directive. All changes are confined to the module declarations in Figure 19.6(d) and (e), so no other changes are required in the code. Implications of using a requires transitive directive are that any module that requires seller now will also implicitly require factory. This implied dependency is shown from client to factory in the module graph in Figure 19.6.

Figure 19.6 Implied Module Dependencies

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *