Are there clear rules on when to use each of these when making classes and interfaces and dealing with inheritance?
views:
15030answers:
7This Java tutorial may be of some use to you.
Modifier | Class | Package | Subclass | World public | Y | Y | Y | Y protected | Y | Y | Y | N no modifier | Y | Y | N | N private | Y | N | N | N
If in doubt, you can always use the most restricting one that works.
Easy rule. Start with declaring everything private. And then progress towards public as the needs arises and design warrant it.
When exposing members ask yourself if you are exposing representation choices or abstraction choices. The first is something you want to avoid as it will introduce to much dependencies on the actual representation rather than it's observable behavior.
As a general rule I try to avoid overriding method implementations by sub-classing, it's to easy to screw up the logic. Declare abstract protected methods if you intend for it to be overridden.
Also use the @Override annotation when overriding to keep things from breaking when you refactor.
The difference can be found in the links already provided but which one to use usually comes down to the "Principle of Least Knowledge". Only allow the least visibility that is needed.
(Caveat: I am not a Java programmer, I am a Perl programmer. Perl has no formal protections which is perhaps why I understand the problem so well :) )
Private
Like you'd think, only the class in which it is declared can see it.
Package Private
Can only be seen and used by the package in which it was declared. This is the default in Java (which some see as a mistake).
Protected
Package Private + can be seen by subclasses.
Public
Everyone can see it.
Published
Visible outside the code I control. (While not Java syntax, it is important for this discussion).
C++ defines an additional level called "friend" and the less you know about that the better.
When should you use what? The whole idea is encapsulation to hide information. As much as possible you want to hide the detail of how something is done from your users. Why? Because then you can change them later and not break anybody's code. This lets you optimize, refactor, redesign and fix bugs without worry that someone was using that code you just overhauled.
So, rule of thumb is to make things only as visible as they have to be. Start with private and only add more visibility as needed. Only make public that which is absolutely necessary for the user to know, every detail you make public cramps your ability to redesign the system.
If you want users to be able to customize behaviors, rather than making internals public so they can override them, it's often a better idea to shove those guts into an object and make that interface public. That way they can simply plug in a new object. For example, if you were writing a CD player and wanted the "go find info about this CD" bit customizable, rather than make those methods public you'd put all that functionality into its own object and make just your object getter/setter public. In this way being stingy about exposing your guts encourages good composition and separation of concerns
Personally, I stick with just "private" and "public". Many OO languages just have that. "Protected" can be handy, but it's really a cheat. Once an interface is more than private it's outside of your control and you have to go looking in other people's code to find uses.
This is where the idea of "published" comes in. Changing an interface (refactoring it) requires that you find all the code which is using it and change that, too. If the interface is private, well no problem. If it's protected you have to go find all your subclasses. If it's public you have to go find all the code which uses your code. Sometimes this is possible, for example if you're working on corporate code that's for internal use only it doesn't matter if an interface is public. You can grab all the code out of the corporate repository. But if an interface is "published", if there is code using it outside your control, then you're hosed. You must support that interface or risk breaking code. Even protected interfaces can be considered published (which is why I don't bother with protected).
Many languages fine the hierarchical nature of public/protected/private to be too limiting and not in line with reality. To that end there is the concept of a trait class, but that's another show.
David's answer provides the meaning of each access modifier. As for when to use each, I'd suggest making public all classes and the methods of each class that are meant for external use (it's API), and everything else private. You'll develop over time a sense for when to make some classes package-private and when to declare certain methods protected for use in subclasses.
This will help you more....
Within Class | Same PKg. | Subclass | Different Pkg
| Outside The Class| Same Pkg.|Diff Pkg.| But not Subclass
PUBLIC | yes | yes | yes | yes | yes
PROTECTED| yes | yes | yes | yes | No
DEFAULT | yes | yes | yes | No | No
PRIVATE | Yes | No | No | No | No