Search code examples
javaeclipseinheritanceclass-visibility

Inheritance and visibility across projects


edit: I only ever used Eclipse to program Java, so all of the following (and all my knowledge on Java) is dependent on how Java is programmed in that environment.

I have two eclipse projects: Project A with class X and Project B with class Y. Class Y from project B extends class X from project A.

public class Y extends X // In short B is dependent on Project A

Class X is public and it has a nested class O.

public class X {

    class O { // default access modifier

    }
}

In my setup, class Y can instantiate O as long as O is not private. Meaning, even if O has a default access modifier, Y can still access O's members and variables. This is confusing to me because I thought default classes meant that foreign classes have access to it only if they shared a common package.

So the conclusion I get from this is that the default package in every project must be the same or connected in some way. Am I correct in thinking this? And if this is correct, will changes made in the package of one project be reflected on the package in the other?

And this presents the main problem I'm dealing with. I want to control access to class O such that in my example, I want Y to not be able to instantiate O. Only way I can do that now is to set the visibility of O to private, but this also restricts other classes from the same project (project A) from accessing O. I want class Y from project B (which I thought had a different package from project A) not be able to access O but some other arbitrary class from the same project as Y/O to have access to O with no problems. How can I do this?


Solution

  • A few different questions here so I'll enumerate them and answer individually. Also, I'll assume that by project you are referring to something like a project in Eclipse.

    1. Am I correct in thinking this?

      Correct, if you have multiple projects (e.g. JAR file build artifact Eclipse projects), each with a default package (e.g. src/main/java/Foo.java in two projects) default scope (i.e. package-private) classes will be able to see each other and their respective public, protected, and package-private methods and fields.

    2. And if this is correct, will changes made in the package of one project be reflected on the package in the other?

      Correct, assuming that the changes of the upstream project are visible to the downstream project.

    3. How can I do this?

      Strictly speaking, you can't unless, as you said, you make it private. And even then, you can circumvent it. However, what you can do is choose meaningful package hierarchies that other coders are unlikely to use. For example, names such as com.acme.myproject.subfolder are common for this reason. But somebody could still create a parallel folder in their own project and call your package-private classes. That being said, for private member classes, they could change the accessibility of that member, thereby circumventing you. While that may sound scary, if you want truly secure code, you really ought to use secure authorization to remote services. The purpose of making something package-private is to prevent it from being part of your API, rather than enforcing some true security. In fact, often this behavior is desirable. For example, suppose I have a package-private class at src/main/java/com/acme/myproj/Foo.java that I want to unit test. The Foo class is package-private because I don't want to make it part of my public API. So, I can just create src/test/java/com/acme/myproj/FooTest.java and voila, I can now execute unit tests against my package-private class Foo.

    I hope that explains things.