Multiple inheritance with a single global ordering of classes

In Common Lisp, Dylan, and Python, all languages that provide multiple inheritance, there is a notion of inheritance order, specified by the order in which the direct superclasses of a class are given. All three languages determine the order in which methods are examined for relevance at method-call time by flattening the direct superclass orders into an order of all the superclasses. If no such flat order is possible, the class is rejected at compile time. (The flattening is done by different rules in each language, but that's not my present concern.)

In particular, suppose a class A and a class B which wlg inherit only from the topmost class. Then we may have a class AB which inherits first from A and then from B if A does not have a suitable method, and a class BA which inherits first from B and then from A. However, a class C that inherits from both AB and BA is not allowed, as its order would be locally inconsistent: we do not know whether to flatten it as C, AB, BA, A, B or as C, AB, BA, B, A.

My question is this: does having such classes as AB and BA ever actually make sense? Are there Real World examples where it is necessary in the same program to have two distinct classes that inherit from the same set of superclasses but in a different order?

I ask this question because I am implementing a language with MI, and it seems to me that there is a considerable advantage to my implementation if I can rule out such combinations of classes tout court, and simply require a globally unique order: if AB exists, then BA cannot, and vice versa. I have asked people from the Python and CL communities, and they tell me that such contrasts are normally considered poor style: that the only thing a method should count on is that methods from its subclasses are tried before it, and methods from its superclasses are tried after it. However, I would not want a win for me to become a loss for my users, so if anyone can point to realistic counterexamples, I suppose I will have to bite the bullet.

Comment viewing options

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

If you can't prove it matters, it probably doesn't

The contortions that one imagines are possible with MI don't seem to come up often in practice, so any reasonably sane scheme should be fine, including reasonable restrictions.

I implemented MI as a result of user demand, in the second major release of a commercial OO language extension product - the first version only had single inheritance. Support for MI-related issues hardly ever came up.

If inheritance order doesn't

If inheritance order doesn't matter maybe inheritance isn't what we are looking for - it seems that when order do matters, inheritance is used for composing implementation(not is-a), and not for abstraction.

While you are experimenting: what if you have single inheritance with another construct for grouping(union) classes into a class Set. For example:

Class Size {}
Class Big extends Size {}
Class Small extends Size {}

Class Karma {}
Class Bad extends Karma {}
Class Good extends Karma {}

Class Race {}
Class Wolf extends Race {}
Class Bear extends Race {}

Class PCDetails {}

types of Classes are also class sets:
Class Size {} :: {Size}
Class Karma {} :: {Karma}
Class Race {} :: {Race}

new constract for grouping class sets into bigger class sets:
type NPC = {Size Karma Race}
type PC = {NPC, PCDetails} :: {Size Karma Race, PCDetails}

now we can write a function:
doSomething(obj:{Size Karma Race}) { ... }

we can construct new objects:
var bbw:NPC = new {Big Bad Wolf}
var hero:PC = new {Big Good Bear Details}

and call a function with:
doSomething(bbw)
doSomething(hero)
calling a function check that: type <: (type ∩ typeof(obj))

This is inspired by Haskell's type-classes.
Still unbaked, but what say you ?

Mixins

If you provide some kind of CLOS :before and :after methods then your inheritance scheme may more conveniently express mix-in modifier classes for which the difference between AB and BA matters (BTW, if you want to support that kind of thing, you might also want repeated inheritance.) Inheritance schemes are typically presented as a big list of rules that might do what you want rather than as part of a principled modeling discipline, so it's hard to give an answer about what's needed in theory.

whence theory?

is there any good theory that helps model all the issues around inheritance, and lets us compare various real world implementations?