An accessor is a type of method used in object-oriented programming languages to return the value of an data member. (Compare with mutator). Public accessor methods are a best practice, recommended by many coding standards as the correct way to access fields of a class, while the member itself can remain private.

Some conventions even mandate that access within the class itself should be through the accessor methods. This ensures that attempts to read the instance variable are all performed at a single point in the code, which can often be of assistance when debugging multi-threaded applications.

The format of an accessor method is uncomplicated almost by definition. For example, given a member variable "balance" of type double, the corresponding accessor would be:

public double getBalance()
{
    return balance;
}

While most accessors take no arguments, on occasion there is value in an accessor that takles an index to return a single element of an array or collection, rather than the entire collection itself. Design patterns such as JavaBeans make use of this kind of convention, and treat such accessors as an indexed property.

Accessors are by far the most important type of setter method. However in many object-oriented languages such as Java, they do present some issues when they are used to access member variables that are themselves objects. The member is returned as a reference, which may allow the caller to inadvertently modify it. This is particularly an issue with collection classes. In other languages such as C++ that support the notion of const, it is a good idea to make an accessor a const method that returns a const reference.

In this age of moral programming, most "good programming guides" stress the vital importance of implementing getThis and setThat methods for every publically-accessible attribute. Supposedly, this way hides the internal structure of the class. Information hiding at its best.

For example, the class Interval might have attributes start and length, so we'd have to write

class Interval {
  double start;
  double length;
public:
  double get_start() { return start; }
  double get_length() { return length; }
  double set_start(double s) { start = s; }
  double set_length(double l) { length = l; }
};

In a stroke, public data members are gone. You are only allowed to have public member functions.

In my running example, supposedly we should hide from the poor programmer that intervals have a start and a length. Obviously, though, any programmer stupid enough not to notice that the above Interval has-a start and a length should probably be assigned as far away from real code as possible, where they cannot do much damage. Perhaps a career in upper management is indicated?

Computing is about data. Programming languages already have ways to read and write data. To read variable x, we usually say "x", not "get_x()". To write variable y, we usually say "y = ...", not "set_y(...)". Except in COBOL, obviously.

People who plan hierarchies full of accessors always seem to me as if they are about to plan a lengthy campaign in Russia with heavy equipment. The end-result is always the same: heavy code, tanks getBoggedDown in autumn, deadlines missed due to unreadable code, resupply impossible when said tanks getFrozenInTheirTracks inWinter.when(), and an end-result of isTotalFailure().

I would implement Interval differently:
struct Interval {
  double start;
  double length;
};

To read the length of interval i, say "i.length". To write the start of interval i, say "i.start = 1.7". The only disadvantage of this elaborate scheme is that suddenly high-level object oriented programming becomes embarrassingly easy. Even an upper-level manager could read code that uses the language, instead of constructing elaborate accessor mechanisms.

Suddenly, an Interval ends at "i.start+i.length", not at "i.getStart()+i.getEnd()". It's all so simple -- and simplicity is the programmer's best -- and only -- friend.

But what if the internal representation if changes?

With accessors, you just need to change their implementation. Of course, suddenly the class interface sprouts new methods to get and set the new data members, but if we ignore that fact then the change really is transparent.

For instance, say we decide to implement Interval as a <start,end> pair rather than as a <start,length> pair. In fact, there can never be a legitimate reason to make such a change, but I shall humour the poor misguided souls who confuse this fake agility of changing unimportant details with the true agility of being able to write and read code.

With accessors, we now have

class Interval {
  double start, end;
public:    // get_start and set_start remain unchanged
  double get_length() { return get_end()-get_start(); }
  double set_length(double l} { set_end(get_start()+l); }
  // get_end() and set_end(double) omitted
};
Fairly easy stuff, especially given you're already used to all those horrible nested braces since you have to use them in application code all the time.

On the other hand, your upper management-level twit is convinced you cannot change the easy version above. Some disabusement is in order, then...

struct Interval {
private:
  class LengthHelper {
    double& start;
    double& end;
    LengthHelper(double& s&, double& e) : start(s), end(e) {}
    friend class Interval;
  public:
    operator double() { return end-start; }
    const LengthHelper& operator=(double l) {  // see C++: (a=b)=c;
      end = start+l;
      return *this;
    }
  }
public:
  double start;
  double end;
  LengthHelper length;
  Interval() : length(start, end) {}
};
LengthHelper explains how to read and write the length of an interval. And it exactly mimics the get_length() and set_length() methods of the accessorized version. Hide it away in some infrastructure library; use some standard template structure to hide trivial calculations from you.

The user can continue to write code that accesses data as though it were data, and doesn't pretend it's doing something hard with all those function calls.

The difference is clear: In the accessorized versions, the creator of the infrastructure tell the application programmer "you need to clutter up every use of my class with get_this() and set_that() methods, because I can't be bothered to do my job". The sane version, above, tells the application programmer "let's start off with a struct; if we need to change something, we can do it, and the complexity stays hidden in the library".

Side effects

Another claim made for accessors is that they allow the programmer to add side effects to the method. Presumably, this is particularly important for the set_that().

But note that the above logic is usable for running arbitrary code during both get_this() and set_that() methods. This code could easily include side effects. The only difference between writing your accessors and allowing the compiler to insert them using a *Helper class is in their syntax.

Why accessors?

Accessors offer nothing. Simple libraries become complex, complex libraries become nightmares. The ability to change interface is paid-for by all users of the library class.

The public interface of a class should be determined by what its users need. Not by what some arbitrary style guide for COBOL decided was simplest. Just as we allow public member functions -- and indeed, we must allow them -- so should we allow public data members.

Non-C++

Java doesn't really let you do stuff like the above example. It is "the COBOL of the 90s". The year is 2005 -- Let's write libraries that let us program in the language. Let's stop using COBOL. Let's demand what we need from the toolchain vendors, from our management, and from their consultants.

Let's keep the simple things simple, so we can do what we need to do: simplify the complex things enough to solve them.

Accessors and mutators ('get' and 'set' methods) are either a necessary evil, or poor programming, depending on your point of view.

In his book on design patterns - 'Holub on Patterns' - Allen Holub has a section in the first chapter called 'Getters and Setters Are Evil'. This is obviously an extreme view! However, he does qualify this position somewhat:

This isn't to say that your functions shouldn't return values or that "get" and "set" fuctionality is never appropriate. ... Nonetheless, get/set functions are often used inappropriately as a means of accessing otherwise private fields, and it's that usage that will give you the most trouble.

Holub characterises misuse of accesor functions as 'laziness' - deferring decisions about object interaction until later. That is to say, when the programmer first creates a class the accessor methods are created along with the attributes of the class. This is especially true for JavaBeans - which are simply Java classes with certain requirements - including the necessity for getX and setX methods for any attribute X. These 'beans' can be created semi-automatically by an IDE (you add an attribute to the bean through some GUI and the get/set methods are created for you).

Whether you agree with this assessment or not, there are other options in other languages. You can make a private inner class in C++ (see ariels writeup) that provides you with a rich attribute that you can 'get' and 'set' with the normal language syntax (e.g. 'instance.attribute = value;' instead of 'instance.setAttribute(value);'). In Python this kind of trick is simplified to use of a property to wrap a method:

class Interval:

        def __init__(self, start, end):
                self.start = start
                self.end = end

        def getLength(self):
                return self.end - self.start

        def setLength(self, length):
                self.end  = self.start + length

        length = property(fget=getLength, fset=setLength, doc='length of the interval')

if __name__ == "__main__":
        interval = Interval(1, 10)
        print interval.length
        interval.length = 10
        print interval.end
 

What the 'length = property(...)' call does is associate the 'length' attribute with the two 'getLength' and 'setLength' methods (and a documentation string). As you can see from the test code at the end, accessing the pseudo-attribute 'length' effectively calls the 'getLength' method, while assigning to 'length' calls the 'setLength' method.

Log in or register to write something here or to contact authors.