Experience with non-linearized superclasses?

Many OO languages with multiple inheritance linearize superclasses, to remove ambiguity. E.g., Dylan and Python both use the C3 algorithm.

Craig Chambers (in the languages Cecil and Diesel) argues against linearization (page 30 in the Cecil spec), and prefers a very simple, so-called "distance metric": a (method from a) class A only overrides another class B, if A is a subclass of B. Order of classes in the superclasses list of a class is ignored. Programmers may have to add methods for disambiguation.

I find Chambers' approach elegant, but I wonder how it stacks up in practice. In case there are any Cecil/Diesel users, or users of other languages without linearization, or anyone with an opinion on this topic, I'd love to hear from you.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

It seems to me that

It seems to me that statically typed languages (and Cecil is in this class if I'm not mistaken) prefer an error in case of ambiguity while dynamically typed languages consider overkill to always gives a run-time error in that case and thus use linearization algorithms to disambiguate when possible (the algorithms may have cases which aren't linearizable).

Superglue

The live version of Superglue does not depend on linearization for MI. Rather, it is much closer to Cecil: connections (statements) to the same port are organized into a circuit and prioritized by type specificity. Subtyping in Superglue is merely a subsetting relationship, so if class A extends B and B extends C, A has the type (A,B,C). Two connections are then ambiguous if they are typed by disjoint sets of classes. Since inheritance in Superglue is dynamic and connections have dynamic guards, ambiguity is a run-time error (otherwise Superglue is statically typed). I was unaware of Craig's position on this (maybe didn't read the papers close enough), but Todd Millstein made a similar observation about resolving ambiguity in multi-methods.

To throw some straw on the fire, Superglue also supports virtual container typing, so if A extends B, and C is a member of B, then the type of C in B is more specific than the type of C in A. Now, if D also extends B, then C in A is ambiguous with C in D. I think this works well in practice, but I'm the only one to have ever used the language!

I found linearization to be a bit dangerous in Scala. You could have trait A extends B,C and trait D extends C,B, when you combine A and D, you could get (A,D,C,B) I think (I would have preferred an error). As a heavy inheritance user, I found myself spending sometime in the debugger to figure out what my classes were really doing. Still, it wasn't horrible, and I think Scala's MI features are very good.