A solution I thought about would be to enhance the language such that it is possible to arrange the package in a hierarchical way and to control access between the ordered packages. In some way it is analogue to the friends concept of C++, but one can control access more fine grained than possible there. The enhancement could be defined as follows:
- Introduction of a new keyword like eg. exportto packagename which is defined in the header of a class in analogy to the import statements. The packages defined here have access to the members as defined in the next section. I am currently not sure if it could be an advantage that all classes in a package MUST have equal exportto statements thus rendering the entire package exported to another package.
- Introduction of a new keyword like eg. exportprivate as modifier to members. These members are exposed accessible to the members of the packages defined in the previous section. These members are packageprivate as well. Protected members are not exported (as in my opinion they neither should be packageprivate as they are today).
These enhancements would offer several opportunities. First, one can arrange packages hierarchical by exporting the sublevel packaged classes to the toplevel package. The classes in the subpackages can be hidden entirely from the API. Second, one can arrange higher level entities such as layers in a way that only a minimal set of classes or members of one entity are visible to another entity. As an example one can make members only visible between neighbouring layers making a cross-layer reference impossible. Or in an MVC pattern it would be possible to put Model, View and Controller each in a separate package (and thus to hide their implementation details from each other) and to expose only the Controller package to the outside application.
Another point I personally find quite annoying is that interface members behave different by default compared to class members. Interface members with no (=default) modifier are intrinsically public whereas class members with no modifier are package private. Since it is possible (and makes sense in my opinion) that interfaces themselves are defined package private it should be possible to do so for their members as well. As an example lets assume an API where you expose a bunch of objects to the outside. Some of these objects can be persisted in some way, but this behaviour should be unintentional for a client of the API. Therefore you would like to mark these objects with some non-public interface which asks for a method save() which can persist the object (thanks to Michael for this striking example). Obviously one does not want to make this method public which is currently enforced even by a package private interface. There can be many reasons why you do not wish or you are not able to introduce an abstract class in your class hierarchy as an alternative. Interestingly, the developers of Java themselves broke this rule by introducing the interface Serializable, which carries implicit methods which can be overridden (readObject(ObjectInputStream) and writeObject(ObjectOutputStream) which both are defined private). Although one can consider Serializable as some abstract class where the definition as interface overrrides the lack of multiple inheritance… As a result I would find it quite useful that at least package private interfaces can have package private members. If there is an export mechanism to come like the one described above, this level of definition should be possible for interfaces as well, of course.