Return Immutables From Accessor Methods

Many accessor methods need to return values which are references to objects which represent a part of the state of the called object; directly returning the state in this form will expose the internals of the called object, and the caller will have the ability to modify that state unpredictably.

This is not a problem if the object returned is immutable - that is, is cannot be changed because it has no methods to change its state (and, of course, its instance variables are all private). Integer, String, and Character are examples of existing immutable classes.

The problem with immutable objects, of course, is that the object whose state they represent often needs to change them! MarkRobinson? has described a solution to this, using an AdapterPattern.

Define a pair of interfaces, one which is immutable, and one which extends it and allows state changes. Define a class which implements each of these interfaces. The immutable implementation has a pointer to the mutable one, and delegates all accessor methods to it, which the mutable one is used only by the owning object.

For example:

 public interface PolarPoint? {
public double getRadius();
public double getAngle();
}

public interface MutablePolarPoint? extends PolarPoint? { public void setRadius( double radius ); public void setAngle( double angle ); }

public class ImmutablePolarPoint? implements PolarPoint? { public ImmutablePolarPoint?( MutablePolarPoint? point ) { _state = point; } public double getRadius() { return _state. getRadius(); } public double getAngle() { return _state. getAngle(); } }

This is a lot more work than the alternative ReturnNewObjectsFromAccessorMethods, but it avoids the need to constantly create new objects on the heap on each method call.

-- RussellGold


There is an easier way; see ImmutableInterface. (JayDunning?)


Of course, you need to be clear about the difference between an object you are not allowed to change, and one which is truly immutable. For example:

  void test( ImmutablePolarPoint? p ) {
System.out.println( p.getRadius() - p.getRadius() );
  }

This won't always print 0, because behind the scenes is a MutablePolarPoint? which another thread could be modifying.

True immutability makes makes it much easier to analyse code statically, for correctness and for optimisation, and its especially important in a multi-threaded environment like Java. -- DaveHarris


The Openstep Framework uses this "trick" for it's collection and simple data objects.

For example there's the following inheritance hierarchy:

 * NSString ----> NSMutableString
 * NSString ----> NSImmutableString
where NSString is an abstract class.

Accessor methods for complex value objects always return objects of type NSString. Because the object's class might be NSMutableString, the returned objects might be mutable.

This means the classes have the following semantics:

 * NSString: A string that might change but you can't change.
 * NSMutableString: A string that you can change.
 * NSImmutableString: A string that never changes.

If you want to keep a NSString object, you have to make a copy from it. The NSImmutableString's copy method just returns itself, NSMutableString makes a real copy.

-- Constantin Szallies


EditText of this page (last edited October 22, 1998) or FindPage with title or text search