staff@cadlab.sublink.ORG (Alex Martelli) (08/08/90)
>In general, multiple inheritance is almost never needed. I have never >seen a published example of a C++ program using multiple inheritance >that couldn't be coded just as easily using components instead. (This This is a major thesis of T. Cargill, and he's been propounding it at Usenix and UKUUG; indeed, he has rewritten all published examples of multiple inheritance in C++, with single inheritance or none at all, and they're better (see the proceedings of the above conferences). >is not true for some other systems, such as flavors.) Sometimes multiple >inheritance is the best way to think of a problem, but it is grossly misused I wonder! Yourdon and Coad, in "Object-Oriented Analysis", claim that M.I. is no doubt great as a CODING technique, e.g. for C++ 2.0, but for ANALYSIS ("best way to think of a problem"), they shun it as leading to unwarranted complication in "modeling the problem space". If the analysis theoreticians want MI only in coding, and the coding freaks want to leave MI for analysis, what does this suggest...? >in the C++ world. I would be happy for people to point me to examples of >multiple inheritance in which it is obviously better than any of the >design alternatives. The best cathegory of examples I have seen in books/articles/talks by Bertrand Meyers, and it has to do with parametric classes with some constraints on operations which need to be available on the formal types which are the parameters. Instead of ad-hoc, weakish expression of the constraints like in Ada, one can say, for example: "generic class AVL_TREE of T:COMPARABLE" to express the fact that the T parameter of AVL_TREE must inherit from COMPARABLE, which presumably one has already coded as an abstract class specifying the comparison operator (including some of its semantic constraints, in assertions); now in the code for AVL_TREE I can invoke the comparison operator on objects of formal type T. With MI, this does not really limit what can be put on an AVL_TREE! Suppose I have a class WORKSTATION, which of course has NOT inherited from COMPARABLE, but does have a SERIAL_NUMBER attribute; I can make a COMPARABLE_WORKSTATION with MI from WORKSTATION and COMPARABLE, by implementing the comparison as being done on the serial numbers, and have an AVL_TREE of them for inventory, look-up, etc. Of course I *could* do the same by just inheriting from COMPARABLE and HAVING a field of type WORKSTATION, rather than BEING a workstation; in general, the IS-A and HAVE-A relations are not as disjoint as one would think in the first place! However, I would then have some trouble applying other WORKSTATION ops & data structures to them. I have obviously not yet thought enough about these topics, but it seems to me they're deeply connected with the dual nature of class inheritance - inheritance of SPECIFICATIONS for an interface, and of IMPLEMENTATION... I would welcome a discussion on this, and of MI in general. Also think of the practical concerns - maybe there are cases where MI would not be needed IF one could redesign each and every class hierarchy from scratch, but MI makes it easier to reuse specs and code, maybe from vendor-bought hierarchies, WITHOUT redesign...? -- Alex Martelli - CAD.LAB s.p.a., v. Stalingrado 45, Bologna, Italia Email: (work:) staff@cadlab.sublink.org, (home:) alex@am.sublink.org Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; Fax: ++39 (51) 366964 (work only; any time of day or night).
cox@stpstn.UUCP (Brad Cox) (08/12/90)
In article <243@cadlab.sublink.ORG> staff@cadlab.sublink.ORG (Alex Martelli) writes: > >>In general, multiple inheritance is almost never needed. I have never >>seen a published example of a program using multiple inheritance >>that couldn't be coded just as easily using components instead. > >I have obviously not yet thought enough about these topics, but it >seems to me they're deeply connected with the dual nature of class >inheritance - inheritance of SPECIFICATIONS for an interface, and of >IMPLEMENTATION... I would welcome a discussion on this, and of MI >in general. You and Cargil are on the money with this issue. There is so much confusion about what OO really means because it seems to offer something for the two traditional camps in software; those who believe software is abstract, like mathematics (who like inheritance & static binding), and those who believe software is concrete, like engineering (who like encapsulation and dynamic binding). By supporting inheritance and encapsulation together, OOPLs are like a handsaw (implementation tool) with a ruler (specification tool) taped onto the side. The result is not totally ridiculous, for having both capabilities in the same tool can be convenient for occasional (hobby) work. But the serious craftsman realizes that specification tools and implementation tools are tools for fundamentally different, but closely related, jobs, and builds up astonishingly diverse collections of specification tools over here and implementation tools yonder; together, but ever apart. My IEEE Software paper (Nov 1990) goes into the distinction between specification and implementation in some detail, and argues that we must stop relying so heavily on inheritance in our implementation tools, and start devoting as much attention to creating specification tools as we have on OOPLs. This doesn't mean ripping out inheritance from existing OOPLs, but just knowing that the meaning of inheritance as supported there is as an implementation tool, not a specification tool. Where inheritance really belongs, and where it offers its greatest potential, is in the (as-yet-nonexistent) specification tools; i.e. specification language "compilers" that compile an input notation, the specification, into but *tests*; executable code, or "gauges", that determine (by testing) whether a given implementation is within tolerance to its specification. In case this isn't obvious, the meaning I'm using for "specification" includes not only *static* specifications (i.e. what method names/types are listed in some interface file; i.e. class Stack has methods push and pop), but *dynamic* specifications (i.e. if I push 1,2,3 on an instance of class Stack, pop should return 3,2,1). Inheritance should work extremely well in this domain, far better than it does in implementation languages. The problems with even simple single inheritance, which become vastly magnified with multiple inheritance, are why we never supported multiple inheritance in Objective-C. Instead, we're focusing on providing multiple inheritance where it might do more good than harm, in a parallel specification language, still under development. Do you think we should call the new one Subjective-C? ;-) -- Brad Cox; cox@stepstone.com; CI$ 71230,647; 203 426 1875 The Stepstone Corporation; 75 Glen Road; Sandy Hook CT 06482
gregk@cbnewsm.att.com (gregory.p.kochanski) (08/12/90)
In article <5456@stpstn.UUCP> cox@stpstn.UUCP (Brad Cox) writes: >In article <243@cadlab.sublink.ORG> staff@cadlab.sublink.ORG (Alex Martelli) writes: >>I have obviously not yet thought enough about these topics, but it >>seems to me they're deeply connected with the dual nature of class >>inheritance - inheritance of SPECIFICATIONS for an interface, and of >>IMPLEMENTATION... I would welcome a discussion on this, and of MI >>in general. > >My IEEE Software paper (Nov 1990) goes into the distinction between >specification and implementation in some detail... > >Where inheritance really belongs, and where it offers its greatest >potential, is in the (as-yet-nonexistent) specification tools... > >In case this isn't obvious, the meaning I'm using for "specification" >includes not only *static* specifications (i.e. what method names/types >are listed in some interface file; i.e. class Stack has methods push and pop), >but *dynamic* specifications (i.e. if I push 1,2,3 on an instance of class >Stack, pop should return 3,2,1). > >Do you think we should call the new one Subjective-C? ;-) Won't the process of writing the specifications be as complex as writing the program, if you want to specify things in such detail that all operations of a class can be tested? Without attempting to make fun of these ideas -- I think that having even a partial automated testing sceme would be a big improvement-- I'd like to point out that these ideas have already appeared, although not yet implemented: <<< TLE::PUBD$:[VAXNOTES]VAXC.NOTE;1 >>> -< VAX C Notes >- ================================================================================ Note 133.0 Subjective C Revealed No replies REX::MINOW 94 lines 3-APR-1985 09:03 -------------------------------------------------------------------------------- Forwarded from the ARPA AI-LIST for your enjoyment: Date: 1 Apr 1985 16:05:34 EST (Monday) From: PSN Development <psn@bbn-noc3.arpa> Subject: subjective C [Forwarded by Susan Bernstein <slb@BBNCCP.ARPA>.] Subjective C, a new programming language. Recently researchers in the computer language field have shown much interest in subject oriented languages. Subjective programming languages draw upon concepts developed in the fields of subjective probability and philosophical subjectivism to enrich the field of programming semantics. `Subjective C' is such a language based on the programming language C. Subjective C grew out of the AI concept of DWIM, or "do what I mean". The subjective C compiler infers the mood of the author of the input program based on clues contained in the comments in the program. If no comments (or verbose identifiers) are present, the programmer is judged to have insufficiently thought out his problem, i.e. to have insufficiently specified the computation to be performed. In this case a subjective diagnostic is issued, depending on the compiler's own mood. Assuming comments or other mood indicators are present, an amalgam of inference techniques drawn from various reputed-to-be-successful expert systems are used to infer the author's mood. A trivial example of a mood revealing comment with accompanying program text is the following: a = a - 1; /* add one to a */ A too simple analysis of the dichotomy between apparent meaning of the statement and accompanying comment is that one of them is in error. A more insightful analysis is that this program should not be allowed to work, even if no syntax errors occur in it. Accordingly, subjective compiler should hang the system, thus inducing the programmer to quit for the night. More interesting cases occur when there is no conflict between program text and commentary. It is these cases where Subjective C is shown to be a significantly richer language than normalcy. Some examples of mood-implying comments found in actual programs are the following: ; Here we do something perverse to the packet. Beats me. In this case, the comment reveals that the programmer does not care what the code does, except that he wants it to be something that subsequent programmers will be shocked by. The compiler uses a variation of its mood-inference techniques to generate code that is suitably perverse by systematically generating actions and evaluating them against the criteria it has synthesized. blt ; hold the mayo The Subjective C compiler evaluates the indicatory content of this comment to discern that the programmer is undoubtedly hungry. Code will be generated that will crash inexplicably, thus inducing the programmer to go to the candy machine and pig out, which is what he wanted in the first place. Subjective C is neither a superset nor a subset of "normal" (if one can apply the term) C, known in subjective parlance as normalcy. However, there is an extensive intersection, if meanings of programs are ignored. The central thesis of research in the field of subjective languages is that the meanings of programs are far more subtle than first appears to the reader (or author). Some examples of mood revealing comments in well known C programs include the following: /* I've been powercoding much too much lately. */ and, /* WARNING: modify the following at your own risk. */ Students of program complexity will be interested to note that the algorithms used for mood inference are of greater complexity than NP complete, which is of one of the first known practical applications of this class of computations. The exact characterization of this class of problems is not yet fully explored, but some initial theoretical results will be published by certain graduate students, real soon now, and no later than next August when their fellowships run out. The subjective C compiler, called "see", will be available (relatively) shortly on all bbn unix systems. Comments can be directed directly to the compiler itself, in the usual fashion.
hansen@pegasus.ATT.COM (Tony L. Hansen) (08/17/90)
< From: staff@cadlab.sublink.ORG (Alex Martelli) << In general, multiple inheritance is almost never needed. I have never << seen a published example of a C++ program using multiple inheritance that << couldn't be coded just as easily using components instead. < This is a major thesis of T. Cargill, and he's been propounding it at < Usenix and UKUUG; indeed, he has rewritten all published examples of < multiple inheritance in C++, with single inheritance or none at all, and < they're better (see the proceedings of the above conferences). < Also think of the practical concerns - maybe there are cases where MI < would not be needed IF one could redesign each and every class hierarchy < from scratch, but MI makes it easier to reuse specs and code, maybe from < vendor-bought hierarchies, WITHOUT redesign...? Let me try to summarize Tom Cargill's position on multiple inheritance (MI): o He has been able to rewrite all published examples of MI using either single inheritance (SI), composition (using member variables), or both. o He feels that the rewritten versions are cleaner and easier to maintain. o One exception which he concedes is in the use of multiple vendor libraries, which might possibly be combined through MI. o In either case, he feels that virtual bases are not necessary because those are ONLY needed when designing in MI and he feels that the alternative designs using SI and composition are better. o Tom is also on the lookout for a use of MI which absolutely cries out for MI and can't be cleanly done any other way. I feel that the concepts of "cleaner" and "easier to maintain" are very subjective. I think that thinking in terms of MI may suggest a solution to a problem more quickly, or may suggest alternate ways of thinking about the problem, even if you don't wind up using MI in the end. In other words, it's a tool in your toolbox that shouldn't be categorically denigrated. I've yet to be convinced one way or the other by Tom's arguments. Tony Hansen att!pegasus!hansen, attmail!tony hansen@pegasus.att.com