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 MagicNumber''''''s 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:''' * A derived class will probably access many variables in the base class, meaning the overhead of calling accessor methods is larger. * People expect base classes and derived classes to be closely coupled. * Often a base class and derived classes will be written together as a unit. The programmer will know both classes and be able to take advantage of close coupling to give an efficient implementation. The programmer should just put a warning in the documentation that these variables should not be accessed directly as they may change in future. * There are some variables that you know when you design the class will never change. For example Sun should have had an integer field and avoid the overhead of the intValue() accessor. We '''know''' programmers wouldn't try to change it because integers are immutable! * OK, so generally it isn't a good idea, but if you were implementing some private class and subclass which would only be used within a public class then it would be OK. ''There might be some value in this argument''. * This is an example of DoTheSimplestThingThatCouldPossiblyWork - the complication of providing accessors is unnecessary and therefore should be avoided. * UnitTest''''''ing should be sufficient to determine any problems arising from variable changes. '''Arguments Against Accessing Variables From Sub-Classes:''' * Accessing variables from derived classes makes the coupling between classes and sub-classes too tight. This is bad from a design point of view. * The compiler/JIT or whatever should be able to remove the method call overhead to any method which simply accesses a variable. * Even if one programmer is designing a class and a subclass, someone else could come along and derive another subclass. Warnings in documentation that variables may change are not good enough, in allowing access you have implicitly made a contract that they will be available and not change in meaning. * The example of the Integer class shows how dangerous allowing access to a variable can be. Somewhere there would be a programmer that didn't know that Integers are immutable and change the value. Since so many classes assume that Integers are immutable that would break a large code base! * With the new assertion mechanism in 1.4, accessor methods can be used to verify pre conditions for setters and post conditions for getters. * UnitTest''''''ing can't be sufficient to determine any problems arising from variable changes, as someone else may have used your class in some way you have not anticipated. ---- 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. UnitTest''''''s 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