the blog for developers

Mutable, Immutable and Generics

Immutable objects help with avoiding bugs. Suppose I have two interfaces implementing the Immutable Interface pattern. One interface for Point and one with MutablePoint. The pattern suggests a cast to ImmutablePoint p; ((Point)p).setX( 1.0 ); get the mutable interface. This isn’t safe and can be replaced with a Generics solution.

First we have the mutable point:

public interface MutablePoint {
   public void setX(int x); 
   public void setY(int y);
}

which we want to create from an Immutable object without a cast:

  Point point = point(10,10);
	
  MutablePoint mPoint = point.makeMutable();
  mPoint.setX(20);

The second benefit beside the missing cast is that users of the Point interface know there is a mutable interface which they can get in a defined way.

The makeMutable() method comes from a generic interface called Mutable

public interface Mutable<T> {
   public T makeMutable();
}
 

which is extended by the Point interface.

public interface Point extends Mutable<MutablePoint> {
   public int getX();
   public int getY();
}

Our Point implementation now only needs to implement MutablePoint and Point. Voila.

public class DefaultPoint implements Point, MutablePoint {
   private int x = 0;
   private int y = 0;
      
   public DefaultPoint(int x, int y) {
      this.x = x;
	  this.y = y;
   }
   
   public int getX() { return this.x; }
   public void setX(int x) { this.x = x; }
   public int getY() { return this.y; }
   public void setY(int y) { this.y = y; }

   public Point point(int x, int y) {
		return new DefaultPoint(x,y);
   }
      
   public MutablePoint makeMutable() {
      return this;
   }

}

A negative side effect is that people who have a reference to a Point object can get a mutable version. When the main point is to have more immutable objects. The other way round is often better, have MutablePoint and create an immutable version.

Thanks for listening.

Update: As pointed out, making an mutable object from an immutable one will break the contract, as will making an immutable one from an mutable one. You do need to copy the object to be safe. For example with a BeanCopier or a copy constructor I’ve wrote about in Beautiful Java: Reflection and the BeanCopier. Better name the method asMutable than makeMutable

public MutablePoint asMutable() {
   return new DefaultPoint(this.x, this.y);
}

About the author

stephan Stephan Schmidt has been working with internet technologies for the last 20 years. He was head of development, consultant and CTO and is a speaker, author and blog writer. He specializes in organizing and optimizing software development helping companies by increasing productivity with lean software development and agile methodologies. Want to know more? All views are only his own. You can find him on Google +

Discuss on Hacker News Vote on HN