You now know the options available to you in defining the access attributes for classes you expect to use to define subclasses. You know what effect the attributes have on class inheritance, but how do you decide which you should use?
There are no hard and fast rules – what you choose will depend on what you want to do with your classes in the future, but there are some guidelines you should consider. They follow from basic object oriented principles:
The methods that make up the external interface to a class should be declared as public. As long as there are no overriding methods defined in a derived class, public base class methods will be inherited and fully available as part of the external interface to the derived class. You should not normally make data members public unless they are constants intended for general use.
If you expect other people will use your classes as base classes, your classes will be more secure if you keep data members private, and provide public methods for accessing and manipulating them. In this way you control how a derived class object can affect the base class data members.
Making base class members protected allows them to be accessed from other classes in the same package, but prevents direct access from a class in another package. Base class members that are protected are inherited in a subclass and can, therefore, be used in the implementation of a derived class. You can use the protected option when you have a package of classes in which you want uninhibited access to the data members of any class within the same package, because they operate in a closely coupled way, for instance, but you want free access to be limited to subclasses in other packages.
Omitting the access attribute for a class member makes it directly available to other classes in the same package, while preventing it from being inherited in a subclass that is not in the same package – it is effectively private when viewed from another package.