I've mentioned before that I think the classical object-oriented programming approach works very well in some contexts, but it isn't useful in all contexts (and indeed, can have a negative impact in some contexts).
As someone who works with XML a lot, I often run into problems with the fact that object-oriented languages allow you to derive new classes by extension, but not by restriction. By contrast, XML Schema types (simple and complex) can be derived by restriction, and it often makes perfect sense to do so. So why don't object-oriented languages support derivation by restriction? [Well, most don't support it, although I think Objective-C may support it.]
It's all because of polymorphism. The idea (as most of you will know) is that if ClassB and ClassC are derived by extension from ClassA, then ClassB and ClassC objects have all of the features of A objects, and can be used wherever a ClassA object can be used. This can be very powerful, I don't deny that, it is often very useful indeed.
However, there are many cases where you don't want all of the features of an existing class, just some of them. What happens if ClassR is derived from ClassA by restriction? Well, you can't use a ClassR object in place of a ClassA object, because it doesn't have all of the methods/fields/etc. of a ClassA object. On the other hand, you can use a ClassA object in place of a ClassR object - since ClassR is a restriction of ClassA, ClassA is an extension of ClassR, and extension allows you to do polymorphism.
So, what derivation by restriction gives us, for object-oriented languages, is a way to define new superclasses of a class after the original class has been defined. Normally, only subclasses can be created after the original class has been defined, unless you go and edit the original class (which isn't always possible or appropriate). [In the example above, ClassB and ClassC are subclasses of ClassA, ClassR is a superclass of ClassA.]
In practice, a difficulty in adding support for derivation by restriction is that there can be complex inter-relationships between the methods and fields of a class, and it may not be simple (or possible) to remove something without breaking something else. This certainly applies to the implementations of methods.
What you can restrict, though, are the available non-private (public, protected, package) signatures of methods and fields. That is to say, you can restrict the external "interface" (in the most general sense) that the class presents to other classes. For Java, this works most obviously with interface classes.
Suppose I have some interface:
interface MyInterface { void methodA(); void methodB(); }
As Java is now, I can extend this interface:
interface Extended extends MyInterface { void methodC(); }
and Extended
is an interface with 3 methods: methodA
, methodB
, and methodC
.
How would restriction work? Well, in XML Schema, it works by explicitly stating the restricted content model of the derived type, and the derived type is then checked to be a proper restriction of the base type. Similarly, it would be straightforward (I believe) to extend Java (etc.) so that in an interface restriction, you list the methods that are in the derived interface, and these have to be a subset of the methods in the base interface. For example
interface Restricted restricts MyInterface { void methodA(); }
would be a valid restriction. However,
interface Restricted restricts MyInterface { void methodC(); }
would be invalid (because there is no methodC
in MyInterface
), so the compiler would flag an error.
You could do a similar thing with implementation classes (not just interfaces), by checking that the restricted class has a set of non-private method/field signatures that are a subset of those in the base class. Indeed, you could also derive interfaces by restriction from implementation classes this way, which would sometimes be useful.
Caveats? Well, this style of derivation by restriction means that the derived class/interface can become invalid if the base class/interface is modified. While that may sound like a problem, it isn't a practical problem in XML Schemas, and I don't think it would be in Java (etc.). It's just something you would know can happen when you use derivation by restriction, and that knowledge would help guide you on whether derivation by restriction was appropriate in a particular context, or not. After all, implementation classes can become invalid when interfaces change, and that is just something we've all learned to live with.
I'm interested to know what you think. Do you agree or disagree? Leave a comment if you have an opinion. Would it be worth proposing it as a JSR (feature addition) for Java? What do you think?