5

I'm building a very simple library in Java, which will be packaged in a single Jar. It should only expose one class: World. The World class uses the subclasses of the Block class, which is in the same package (com.yannbane.a), and doesn't provide a lot of functionality itself, but needs to be extended. I planned to create another package, com.yannbane.a.blocks, which would have all the block types (subclasses).

The directory/package structure should, therefor, look like this:

com/
    yannbane/
        a/
            World.java
            Block.java

            blocks/
                Brick.java
                Stone.java

However, in order for the subclasses of Block to actually extend the Block class, I needed to make the Block class public. This destroys my goal of having the Jar file only expose a single class, World. I also need to make the subclasses public so the World could use them.

How can I retain this package and directory structure but still have my Jar only expose the World class, not other classes?

corazza
  • 31,222
  • 37
  • 115
  • 186
  • *Why* did you need to make the subclasses public? That's not clear... – Jon Skeet Oct 17 '12 at 22:17
  • can you make Block an inner class to World that is private and not accessible from the outside? – amphibient Oct 17 '12 at 22:18
  • 1
    If all you intend to expose is the World class why does it matter where the other classes are located. They might just as well be located in the same package and you would not have this kind of problems. Don't you think? – Edwin Dalorzo Oct 17 '12 at 22:20
  • @EdwinDalorzo, I do think, yes, and that would be one of the solutions to my problem. But, I thought that using a logical directory-structure was preferred, so I wanted to do it right. – corazza Oct 17 '12 at 22:21
  • @javaStudent I read somewhere that classes can be either public or default, I'll check it out. Although neither `protected` nor `default` would help me, I think, because the classes are in different packages. – corazza Oct 17 '12 at 22:22
  • 1
    @foampile - If `Block` is a `private` inner class of `World` it can't be extended by any types defined outside of `World`. – Richard JP Le Guen Oct 17 '12 at 22:26
  • possible duplicates: http://stackoverflow.com/questions/4388715/java-expose-only-a-single-package-in-a-jar-file http://stackoverflow.com/questions/6642909/providing-java-library-but-hiding-some-classes – Oded Ben Dov Aug 14 '13 at 13:48

2 Answers2

3

If this is a matter of encapsulation, and all you want to expose to the world is the "World" class, then it does not matter if the unexposed classes are located in the same package or if they are inner classes in the same package.

At any rate, they will not be accessible to the users of your API. I believe encapsulation is more important here than the "logical" organization that you want to give your files. Because if you locate all your classes in the same package, then you will not have these problems and you will achieve the level of encapsulation that you are seeking. Perhaps what Java is telling you is that these classes are so inherently related that you should place them all in the same package.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
1

Make the classes public but their constructors protected.

You still technically expose the classes - other packages are aware of them - but no other packages can instantiate those objects.

Even though the Block subclasses are in a different package from Block (com.yannbane.a and com.yannbane.blocks) they will be able to invoke the protected parent constructor, because protected members are accessible from the same package or from an inheriting object.

Richard JP Le Guen
  • 28,364
  • 7
  • 89
  • 119