[wingide-users] Graphical tree browser?
tms at zeetix.com
Tue Apr 20 20:34:18 MDT 2010
In my 28 years of doing OO tools, systems, and programming -- starting
with Smalltalk in 1982 -- I've never *needed* multiple inheritance. The
problems and complexity it introduces nearly always outweigh the
superficial gain it promises.
The most compelling example that I've run across where MI is tempting is
in the modeling of "Matrix" in matrix arithmetic. It certainly wants to
be a kind of "Collection", or even "Array", because it certainly has
most behaviors that Array instances have -- "row count", "column count",
"index", "item count", etc. It also wants to be in the Magnitude
hierarchy so that it can participate in numerics -- "+", "-", "*" and
"/" at a minimum.
The truth is, though, that I've never actually *NEEDED* to solve this
problem. I'm reasonably certain that the various alternatives enumerated
by Mitchell are more than sufficient if so. Picking one and mixing in
the other -- especially by simply adding a clump of methods to the class
(a "class extension" in IBM-Smalltalk terms) -- is perfectly adequate.
Ultimately, a VisualAge-style tree browser for single-inheritance
is a compelling win. Most real-life MI hierarchies can be supported by
replication (repeat the same tree under its multiple parents). My vote
would be to just say "this tool doesn't support diamond inheritance" and
move on. For most problems faced by most OO developers, this is plenty
good enough and is a SIGNIFICANT advance over the non-hierarchical
alternatives available today.
Mitchell L Model wrote:
> Some further comments on multiple inheritance.
> C++ ran into the diamond problem early on, and for a while kept changing its solution. In the end, the solution to naming conflict is usually to qualify the conflicting names with the name of the class you intend. A perhaps more problematic issue arises in diamond structures: when the root of the diamond actually allocates space -- the canonical example being an IOBuffer, subclassed as either a ReadBuffer or WriteBuffer, with a MI ReadWriteBuffer -- should instances of the MI class get two separate spaces for the IVs inherited through different paths? Seems dumb.
> Smalltalk-80, but I don't think VisualWorks -- or maybe it was just some kind of add-on -- had a crude "make a new class that acts as if it inherits from these others, implemented by delegation of each method from a parent to an instance of the parent in an instance of the MI class. In the case of a conflict, I think it just defined an empty method and left you to figure it out. An interesting demonstration of the equivalence of delegation and inheritance.
> My general tendency is to say MI is best used for small independent features -- i.e., mixins -- that get added to more substantial classes, but not to merge two substantial classes through MI. But that opens up the path to a combinatorial explosion as in the Zetalisp window system where you had classes like SplitPaneScrollableWiindowWithFonts or something like that, as opposed to, say, FancyTitleScrollableWiindowWithFonts or FancyTitleSplitPaneScrollableWiindowWithFonts. Though it seems like a good idea at first, it leads to insanity and, I think, demonstrates the superior approach of frame-based representations in which an instance is just a bare item to which instantiated role-classes get attached. (Moreover, this allows dynamic classification, which is still methodically -- so to speak -- overlooked today: I really don't understand how serious rich-domain systems can be built without dynamic classification. What do you do with your apartment building when it goes co-op?
Or, to cite an example frequently used in basic OO instruction, an employee gets promoted to a manager (the examples distinguish statically between the two classes Employee and Manager without addressing the issue of how an instance of the first changes to an instance of the second).
> MI is also useful for, as you mentioned, combining interfaces and implementations, which is what is done in a lot of C++ libraries and in Java. (However, Java loses completely by not allowing state in its "interfaces".)
> Ultimately, you never actually need MI, since you can always make a composite and delegate to its components even though the result is not really a Composite kind of thing, or you can implement a role-based system. To some extent it's just a convenience, and a way to automatically inherit changes made to multiple ancestor classes without having to manage those explicitly. Maybe it's best left as a design concept and a deep system technique for interface+implementation data structure classes. I don't really know -- I am disturbed by languages that don't support MI, but in practice I rarely use it. MI gives rise to an infuriating range of issues that need to be solved one way or another, whether with classic MI or something else, and it's difficult to find a consistent, practical, and sufficient approach -- maybe there's even something about it that violates some kind of law about self-referential systems, or complexity or something that leads to conceptual and implementatio
nal explosions as soon as you open the door to it. (Thus Java's insidious limitation of interfaces to, well, just interfaces, which do pretty much nothing except enslave humans in the activity of doing the computer's work by telling it variable types.)
Tom Stambaugh, Founder
63 Boston Ave
Somerville, MA 02144
More information about the wingide-users