Gesticulations and Other Geekery » Generalizing “const”
Gesticulations and Other Geekery » Page 'Generalizing “const”'

Generalizing “const”

One of the common complaints that people have about Java is that it lacks the const keyword. Yes, Java has final, but final cannot create a reference to a immutable object only a immutable reference to a mutable object.

The issue is that there is no way to encode the promise that an object will not be mutated in the Java language. The work around for this is to create a wrapper object that throws an exceptions if a mutator method is called. This is how the collection API handles the problem. However this technique provides no compile time checks. There is no way to know at compile time if a given Collection is mutable or immutable.

I have thought about this a bit lately and I have realized that const as it is implemented in C++ is fundamentally a way of defining a sub-interface of the interface to a class. I mean this in the sense that the interface of “const Thing” is a subset of the interface of “Thing”. So in essence “const Thing” can be thought of as a abstract base class of “Thing” (with the exception that casting “const Thing” to “Thing” should be hard or impossible). What I’m getting at is that you could generalize this idea into the idea of a interface subset.

In Java this could be implemented by hand as follows:

public interface ConstThing {
	public String getValue();
}

public class Thing implements ConstThing {
	private String value;

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
}

public class ConstThingProxy implements ConstThing {
	final private Thing subject;

	public ConstThingProxy(Thing subject) {
		this.subject = subject;
	}

	public String getValue() {
		return subject.getValue();
	}
}

// Usage:
public class Client {
	public void useMutable(Thing t) {
		t.setValue("New");
	}

	public void useConst(ConstThing t) {
		t.getValue();
		t.setValue("New"); // <-- Compiler Error
	}

	public void useConstCast(ConstThing t) {
		t.getValue();
		((Thing) t).setValue("New");
		/*
		 * No compiler error, but there would be a runtime error if the code
		 * providing the ConstThing wrapped the reference in a
		 * ConstThingProxy.
		 */
	}
}

Obviously this has a number of missing features and is hard to do because the interface must be declared by hand. So the main missing features from this approach are (in rough order of importance):

  1. There should be an easy way to create this structure of classes. In other words, there should be syntactic sugar for it or something like that.
  2. There should be a way to make the this reference in a function be an instance of all of the interface subsets that the method it part of. This would allow the compiler to provide warnings or errors if the method references elements of the class that are not part of the interface subset. This is actually a very complex problem, especially when combined with inheritance. I don’t have a solution for it that I am comfortable with.

I may come back to this subject later. For instance I think it would be interesting to see if it can be implemented better in Scala with it’s more expressive type system.

Posted in Java, Programming Theory

One comment to “Generalizing “const””

Leave a comment