2

Is it possible to create inheritance-based (or nested) modules in Java 9?

Something like this:

module a
   |
   ├── module a1
   |   
   └── module a2

In this example, both the a1 and a2 modules are children of a.

If I import either of the child modules, I would get the functionality of the parent (a) along with any functionality defined in that child. That is, I could import a1, and explicitly gain access to the functionality of both a and a1 (but not a2).

Both a1 and a2 are an a, and can access all of the packages of a, without having to expose the packages of a to them.

Hamid Mohayeji
  • 3,977
  • 3
  • 43
  • 55
  • 1
    I don't really understand what are these relations between modules. Does `a` require the `a1`? The opposite? What does it mean "dependencies of module a is based on a1"? What does it mean with behavior? It's a lot less general question which you seem to believe. – M. Prokhorov Feb 12 '18 at 13:22
  • 4
    It would be useful to expand the question to explain what you are trying to do. Maybe you want module a to be an aggregator module (`module a { requires transitive a1; requires transitive a2; }` so that anyone that requires a will be able to access the APIs exported by a1 and a2? – Alan Bateman Feb 12 '18 at 13:27
  • 2
    @AlanBateman I took it to mean the opposite; there are two externally-facing modules (`a1` and `a2`) which are both `a` modules (in that they can access all of the packages of `a`, without having to expose the packages of `a` so that they, themselves, can access it). Which is to say, I agree the question should be clarified. – Ironcache Feb 12 '18 at 13:31
  • 1
    If what I stated is the desired behavior, I'm not sure you actually want this, in general; what is stopping me from saying that I'm a submodule of `a` to access otherwise-inaccessible elements of `a`? It's compromising security. If `a` was to allow submodules of itself, then I think, for security, you would want those submodules to be explicitly spelled out in `a` (not allowing just anyone to claim they are a submodule). You might be able to handle what you want with `exports X to Y`? – Ironcache Feb 12 '18 at 13:36
  • In some other programming languages environments, like ```php```, there is a concept called nested modules. In this concept a module (parent) is created using multiple modules (child). The overall functionality of the parent module is the functionality of the parent module itself, plus the functionalities which those child modules provide. For example if you want to execute the child module, the parent module will be executed either. I know it seems a bit weird and having this hierarchical structure is not necessary, but I wanted to know of there is such thing in Java 9. – Hamid Mohayeji Feb 12 '18 at 13:42
  • 1
    @HamidMohayeji, we aren't using PHP here, and java modules are different from PHP ones. There is no notion of module being "executed" in Java. – M. Prokhorov Feb 12 '18 at 13:44
  • @M.Prokhorov I just gave you an example. But anyway thanks for reminding me we are not using ```php``` here. – Hamid Mohayeji Feb 12 '18 at 13:50
  • 1
    @HamidMohayeji I have edited your question with my understanding of what you desire. If you feel this is not correct, please clarify the question. If you feel like the question as worded is what you are looking for, then check my answer below. – Ironcache Feb 12 '18 at 14:30
  • @HamidMohayeji With respect to your edited question, the answer is (at the time of writing) that it cannot be done. With respect to the statement "[...] can access all of the packages of `a`, without having to expose the packages of `a` to them.", it would generally be unsafe if modules could be utilized in such a way. The purpose of Java modules are to restrict visibility (in a more versatile manner than the previous packaging mechanics allowed), and this would tear apart those restrictions. `a` needs to be in control of how it exports. – Ironcache Feb 12 '18 at 19:06
  • @Ironcache thanks a lot. – Hamid Mohayeji Feb 13 '18 at 11:07

1 Answers1

7

You can emulate what you asked for with a combination of requires transitive and exports to syntax:

  • requires transitive: Specifies that importing this module will inherently import another module. You can use this to ensure that a1 and a2 cause a to be imported.
  • exports to: This will let you export functionality to a specific module only; this will allow you to let a give access to a1 and a2 functionality that would be dangerous to have publicly exported.

So, for examples sake:

module a {
    exports com.internal to a1;
    exports com.internal to a2;
}

module a1 {
    requires transitive a;
}

module a2 {
    requires transitive a;
}

In this case, if a consumer depends on a1, they will inherently depend on a (thus gaining the utilities of both), and the com.internal package, while visible to a1 for internal use, will not be externally visible to the consumer.

It is not quite what you asked for. a1 is not an a. Further, a1 can not be made to be an a; the JLS does not allow for wildcards in exports (IE: exports * to a1, which still wouldn't make a1 an a but would bring it closer from a pragmatic perspective), and no other syntax exists in modules to allow for it.

Ironcache
  • 1,719
  • 21
  • 33