Should Member Variables Be Accessible To Derived Classes

I believe it is generally accepted that member variables of a class should not be directly accessible to classes outside the inheritance hierarchy. Accessor methods should always be used so that the implementation of the class can be maintained whilst providing the same interface. The one exception would be constant or static final methods in Java, which are often required to avoid passing MagicNumbers to classes.

When it comes to accessing methods from within the inheritance hierarchy I have heard arguments for and against allowing direct access to variables:

Arguments For Accessing Variables From Sub-Classes:

Arguments Against Accessing Variables From Sub-Classes:


I've moved from the make them available to the not make them available camp. I've been bitten numerous times that I couldn't change base class behavior because derived classes had made extensive use of the attributes instead of using the higher level methods. One exception to this is a semaphore because the entire object needs to use the same base class semaphore. -- AnonymousDonor


I believe any proponent of DoTheSimplestThingThatCouldPossiblyWork would naturally tend to believe that get/set methods are evil. If you want access to a member variable, just make it public. Otherwise, you are creating unnecessary complication. UnitTests and the compiler will protect you if you ever want to change your mind. The corollary then would be let derived classes have access to member variables if they want access to member variables. -- SunirShah

The reason i don't agree with this position is that allowing access to bare variables makes it impossible to add in more specific checks or add in related behavior. For example is the state of a variable changes and then someone wants to listen to this change, then all raw access are untrappable. For example if another check on the format of a string needs to be added then all raw access are untrappable. As I'm not a do the simplest thing that could possible work type of person i take these issues into consideration, especially on large products where refactoring is extremely painful. -- AnonymousDonor

Generally I won't mind exposing member variables within a system, but I would avoid it if the class is part of a published API. This goes for derived classes too. If I intend a third party to write the derived classes I would hide the member variables. -- AndersBengtsson

In general, you should not need either direct access or accessors. You should provide methods that perform an operation and not require intimate knowledge of variable state within a lower level class. If you run into this situation, see if it does not make more sense to either push the variable up a level or pull the method modifying the variable down a level. -- WayneMack


I believe any proponent of DoTheSimplestThingThatCouldPossiblyWork would naturally tend to believe that get/set methods are evil. I'd say, rather, that get/set methods should not be used prematurely. As soon as there's a legitimate reason, refactor an exposed variable member to one or more accessor functions. Legitimate reasons for this include needing to listen for value changes, or the need to expose the class publicly to many other modules or to any other modules that are not under your control, such that the use of bare variables would make the code too fragile.


Alternative solution: ObjectPascal uses property, and this dilemma just disappears. The setXXX/getXXX convention ( or any other convention with regards to getter/setter) is obviously an ad-hoc workaround for a language design issue.

Property is a pretty heavyweight construct for every object attribute? -- AnonymousDonor

No it is not, if you don't link the property to specific read/write functions, the compiler generates the same code as to read/write of a public variable. A property name is almost like a macro. It is a design decision whether the access to an instance variable should be mediated or direct. Most of the times read access is direct, while write access is mediated by a write procedure. I believe the same thing applies to VisualBasic.

Example design:

  if (window.visible) then ...

may generate a direct read access of a visible instance variable while

  window.visible:= true;

may generate a call to a setVisible(value:boolean) that will first try to switch the visibility on the screen according to the new value, and after that set the fvisible private variable. This is very simple, effective and easier to read.

Won't the javac compiler and hot spot compiler also reduce simple accessors and setters to direct access?


I usually find that if I am modifying base class variables in a derived class, I have a bad class decomposition. Consider: merging the classes, moving the variable(s) up a level, creating an abstract method in the base class, or creating an intermediate class level. Having operations on a variable split between two classes is an indication of poor encapsulation. -- WayneMack

But that's the point. What is the degree of encapsulation required between base classes and derived classes? You are saying the encapsulation should be complete. There are arguments the other way as well. -- AnonymousDonor

The purpose of encapsulation is to co-locate all operations on a variable. This allows one to view all possible changes to a variable in one place, the class file. As more files have to be opened to view the operations on a variable, the difficulty in tracking the operations and keeping them consistent increases. In practice, I have rarely found bugs because an individual function operating on a variable was miscoded. What I have found numerous times are interaction problems where one function makes a change that another function is unable to handle. Make life easy on yourself and other developers and get all of the functions operating on a variable into one file and keep that file as small as possible. -- WayneMack


You are saying the encapsulation should be complete. There are arguments the other way as well. -- AnonymousDonor

What are these arguments? Are there any specific examples where complete encapsulation is not superior? The only example I have ever run across is when you are forced to use encapsulation to emulate multiple inheritance.

Operations on streams. Classes like 'InputStream?' in the java io library are meant to be plugged together into a pipeline to provide the desired functionality. They do not encapsulate actions on the data in a single class, instead actions are spread across many classes, which are then assembled into a pipeline. (each individual action does use information hiding to prevent us from seeing how it is implemented, but this is different from encapsulation - the two things often get confused). There is a discussion of this difference between stream- and object- oriented programming in the StructureAndInterpretationOfComputerPrograms, IIRC. Somewhat off topic for this page, but it does point to some situations where encapsulation is not the best solution -- BrianEwins


It seems to me that frameworks are most commonly extended by subclassing. It further seems to me that the degree of encapsulation assumed by such extensions needs to be carefully controlled. The sharing of member variables, in addition to methods, adds yet another dimension of difficult decision making with a simultaneous multiplying of risk. My habit is, therefore, to make every member variable private and accomplish whatever sharing is needed through the judicious use of accessor methods. I am beginning to suspect that limiting the scope of the member variable name space to the defining class would ease subsequent refactoring -- TomStambaugh.

It does, and (if you are using java) it also helps tools like Eclipse and Ideaj analyse your code and spot unused stuff. -- TomAyerst

I would suggest that frameworks provide the most common example where encapsulation is violated. Frameworks are bound primarily by operation (procedural decomposition) rather than data (object oriented decomposition). Most GUI classes and components are thinly disguised operating system calls that are not really bound to the final operation of the software (How could they be? They were written well before the application!). I am not going to argue that the common developer avoid using frameworks because of this, but I also note that the rise in use of GUI frameworks has corresponded to a rise in difficulty and faults arising in user interfaces. I continue to wonder if there is not an underlying architectural problem with most frameworks, while recognizing that it is not pragmatic for most developers or projects to try and resolve this problem; they need to take what is available and do the best they can with it. -- WayneMack


If your classes are tightly coupled enough to warrant inheritance then the derived classes should be able to access the members of the superclass. If they are not then you should be using interfaces/abstract classes with composition/aggregation not inheritance. -- TomAyerst

I would suggest that if the methods in a base and derived class are coupled by a common data element, then those methods should be merged into a single class that is contained and used by the derived class. In practice, I have found that "split accesses" to data members usually results from trying to use inheritance rather than composition for method reuse. After applying this transformation, I usually find the result much clearer and easier to modify. -- WayneMack


See AccessorsAreEvil, ForgetAboutWritingAccessors


EditText of this page (last edited March 4, 2005) or FindPage with title or text search