pcg@cs.aber.ac.uk (Piercarlo Grandi) (11/24/90)
On 21 Nov 90 12:11:00 GMT, johnson@m.cs.uiuc.edu said: johnson> pcg@cs.aber.ac.uk said: pcg> Abstract (deferred) classes are no good of course. They are just a hack pcg> to decouple a bit the algebra of interfaces from that of pcg> implementations, which are otherwise coupled in inheritance. johnson> I am shocked! What can this mean? Abstract classes are one of johnson> the most important design techniques in object-oriented programming! I am sorry to distress you, but I really meant that, literally. I agree that they are one of the most important things in OO programming, but only because OO programming as we know it now is very limited and flawed. In other words, I don't believe that classes as we know them now are OO programming's best friend (see the "is CLOS OO?" thread in comp.lang.clos). I will engage in restating my view of OO programming (I love to read my own words! :->): Assuming that we have a matrix indexed by type and operation, and whose entries are implementations, OO programming is that style of programming where it is assumed that _most often_ the best way to minimize inter module dependencies and maximize reuse of interface, implementation, and specification is to "cluster" (whatever that means...) implementations by type rather than by operation. This assumption is based on the idea that implementations of different operations on the same type are more intimately related than those of the same operation on different types. In other words OO programming is based on *overloading*, either static or dynamic (polymorphism). As a trivial example, real and complex numbers have the same interface, but very different implementations (and, in a way, specifications). Using OO programming with static or dynamic overloading means that the programmer can (statically or dynamically) abstract programs syntaxes over the reals or the complexes, without great effort. Naturally this is *often* but not always true; for example if the types are strongly related by specification, e.g. for all types whose specification is a particular mathematical structure (hints of category theory here...) then the implementations of the same operation for all such types will often be strongly related. This is a good reason for *genericity*, either static or dynamic. As a trivial example, stacks and queues over any other type share much the same specification (they are indeed both subsets of deques), and thus the implementations of 'push' and 'pop' will be written identically for all subtypes of stack, and they will be almost identical to those for 'next' and 'first' for a queue. Traditional OO technology is forever torn (see the discussions in this group) between overloading (abstraction on interface) and genericity (abstraction on implementation), because there are languages like Smalltalk in which the two are not spearated, and other like C++ where they are not well separated. johnson> Reading on, I decided that Piercarlo and I have different johnson> definitions of abstract classes. I think that he defines an johnson> abstract class as one that has NO implementation, in which johnson> every method is deferred. However, my definition of an johnson> abstract class is that it is a class that does not have a johnson> COMPLETE definition, in which there is SOME method that is johnson> deferred. No, no, this is not my point. I accept that abstract classes can be not just interface but also implementation templates. But I don't like them being *both* -- I would like there there were different notations and more orthogonal algebras for mix and match of interfaces and implementations (and specifications). Deferred classes which are also implementation templates are really about genericity, not overloading like conventional classes are. Mixing the two technologies makes me uneasy. Indeed: johnson> Abstract classes according to my definition are a crucial johnson> technique for reusing classes. An abstract class is a template johnson> for its subclasses, and replaces other ways of reusing design johnson> such as code skeletons. Yes, as agreed above. But the point here is that (my usual party line) one wants to abstract over types and functions along three dimaensions, interface, implementation, specification. Non deferred classes allow for reuse of interface and implementation on one type, with method overloading; pure deferred classes allow reuse of interface decoupled from that of implementation; a deferred class with methods is a way to reuse interface and have generic implementations. johnson> I agree with Piercarlo that abstract classes should not be used johnson> just to represent types (though of course if you are johnson> programming in C++ then you have no other choice). Thus, we johnson> probably don't really disagree. Yes :-). Actually I also think that the problem is there also in Smalltalk, where you also have really no other choice. Ther eis some better hope in Self, Trellis, and CLOS (especially the latter, where you can define any metaobject protocol). -- Piercarlo Grandi | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk