richieb@bony1.bony.com (Richard Bielak) (04/23/91)
One of the things I liked about "Object Oriented Software Construction" by B. Meyer, was the idea that a class is both a type and a module. This idea clears up the confusion as to whether inheritance extends or specializes. When a class is considered to be a type, inheritance specializes the type. The descendent type is type-compatible with fewer things, so it is more specialized. When a class is considered to be a module, inheritance adds more routines and attributes. Since the class can do more things it has been extended. I also like the "cleanness" and simplicity of this idea. I am curious whether other people think about this, and whether such "unification" has any disadvantages. ...richie -- *-----------------------------------------------------------------------------* | Richie Bielak (212)-815-3072 | Programs are like baby squirrels. Once | | Internet: richieb@bony.com | you pick one up and handle it, you can't | | Bang: uunet!bony1!richieb | put it back. The mother won't feed it. |
davis@barbes.ilog.fr (Harley Davis) (04/24/91)
In article <1991Apr23.142800.12215@bony1.bony.com> richieb@bony1.bony.com (Richard Bielak) writes:
One of the things I liked about "Object Oriented Software Construction"
by B. Meyer, was the idea that a class is both a type and a module.
This idea clears up the confusion as to whether inheritance extends or
specializes.
When a class is considered to be a type, inheritance specializes the
type. The descendent type is type-compatible with fewer things, so it
is more specialized.
When a class is considered to be a module, inheritance adds more
routines and attributes. Since the class can do more things it has
been extended.
I also like the "cleanness" and simplicity of this idea.
I am curious whether other people think about this, and whether such
"unification" has any disadvantages.
For me, a module is a higher-level structuring tool than a class. A
module pulls together a set of classes, functions, methods, and local
data which form a coherent design unit. A class is just one of the
possible implementation choices for a module; not everything need be
tied to a class. This is approach taken by, for example, EuLisp and
Le-Lisp version 16.
While classes could be identified with modules, I find that in real
cases this forces too fine-grained a separation on the implementation.
It is difficult to define a module containing an entire class
hierarchy with associated operations, all exported as a unit.
In this view of the world, the two kinds of inheritance provided by
importing modules and subclassing more or less solve the two goals you
mention separately - ie, subclassing specializes, and module
importation extends. However, I don't see this correspondence as
being essential.
-- Harley Davis
--
------------------------------------------------------------------------------
nom: Harley Davis ILOG S.A.
net: davis@ilog.fr 2 Avenue Gallie'ni, BP 85
tel: (33 1) 46 63 66 66 94253 Gentilly Cedex, France
schwartz@groucho.cs.psu.edu (Scott Schwartz) (04/25/91)
richieb@bony1.bony.com (Richard Bielak) writes: | One of the things I liked about "Object Oriented Software Construction" | by B. Meyer, was the idea that a class is both a type and a module. | This idea clears up the confusion as to whether inheritance extends or | specializes. | | When a class is considered to be a type, inheritance specializes the | type. The descendent type is type-compatible with fewer things, so it | is more specialized. | | When a class is considered to be a module, inheritance adds more | routines and attributes. Since the class can do more things it has | been extended. | | I also like the "cleanness" and simplicity of this idea. | | I am curious whether other people think about this, and whether such | "unification" has any disadvantages. Since no one else has stood forth on the issue, I will. (Let me admit in advance that I've never written an Eiffel program in my life; these comments are motivated by experience with C++. If a free eiffel compiler were available, I'd probably use it.) I don't much like using classes as modules. They seem well suited to building abstract data types, which means they do some encapsulation, but that is no substitute for a real package system that lets you encapsulate a group of ATDs. You mention two ways to use inheritance. It seems to me that these two goals often get in each other's way; as a result there is real disagreement on what inheritance is all about (I recall a paper "inheritance is not subtyping" in a recent TOPLAS, for example.) Eiffel's use of covariance and conditional assignment makes the kind of extensibility that class-as-module requires possible -- it's much harder in C++ where both of those are forbidden by the type system. I feel like modularization is more useful than subtyping. In that light, I agree with lots of Wirth's design choices in Oberon.
sakkinen@jyu.fi (Markku Sakkinen) (04/25/91)
In article <DAVIS.91Apr24143741@barbes.ilog.fr> davis@barbes.ilog.fr (Harley Davis) writes: > >In article <1991Apr23.142800.12215@bony1.bony.com> richieb@bony1.bony.com (Richard Bielak) writes: > > One of the things I liked about "Object Oriented Software Construction" > by B. Meyer, was the idea that a class is both a type and a module. > ... I think this is essentially the "orthodox" object-oriented attitude in general. > ... > I am curious whether other people think about this, and whether such > "unification" has any disadvantages. > >For me, a module is a higher-level structuring tool than a class. A >module pulls together a set of classes, functions, methods, and local >data which form a coherent design unit. A class is just one of the >possible implementation choices for a module; not everything need be >tied to a class. This is approach taken by, for example, EuLisp and >Le-Lisp version 16. > >While classes could be identified with modules, I find that in real >cases this forces too fine-grained a separation on the implementation. >It is difficult to define a module containing an entire class >hierarchy with associated operations, all exported as a unit. > ... In conventional OOP, an entire class hierarchy is certainly not a unit or module. In fact, open-endedness for inheritance is perhaps _the_ strong point of OO reusability. Otherwise, I agree with Davis against the more orthodox view. Thus, the package/module facilities of e.g. Ada and Modula-2, when wisely used, are more versatile than the "one type at a time" approach of CLU (the original ADT language) and most OOPL's. Also, in typical OOPL's, every operation has exactly one "participant" object that is in a distinguished role: the owner or "self"; any other "participants" are considered arguments. I suggest that as many operations as possible should be defined _on_ classes instead of _in_ them, i.e. without a distinguished participant. On the other hand, there are situations which crave for more than one "owner" in an operation: just look at the unnatural way in which ordinary arithmetic operations are defined in Smalltalk. I have not read about any object-oriented language that would allow several owners in an operation (unless the specification language DisCo is counted). In the generic functions (multi-methods) of CLOS, the _selection_ of actual method(s) to be invoked can be based on more than one argument, but in the _execution_ there is only one "self". Apologies if I am repeating some of my earlier ramblings too much ... Markku Sakkinen Department of Computer Science and Information Systems University of Jyvaskyla (a's with umlauts) PL 35 SF-40351 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address)
barmar@think.com (Barry Margolin) (04/26/91)
In article <1991Apr25.074758.6153@jyu.fi> sakkinen@jytko.jyu.fi (Markku Sakkinen) writes: >I have not read about any object-oriented language that would allow >several owners in an operation (unless the specification language >DisCo is counted). In the generic functions (multi-methods) >of CLOS, the _selection_ of actual method(s) to be invoked can be based >on more than one argument, but in the _execution_ there is only >one "self". This is incorrect, CLOS has no inherent notion of "self", neither at method selection time nor during the execution of the methods. All the parameters are accessed by name. WITH-SLOTS and WITH-ACCESSORS can be used to make the slots of instances accessible as if they were variables, but this is not done automatically, and can be done for more than one argument, or even for something that isn't an argument (CLOS provides no information hiding or visibility control -- everything is public, and programmers are expected to use other mechanisms, such as packages to implement visibility control). In generic functions where there's only one argument that is used to control method selection, some people have a convention of calling the argument SELF in the method definitions (in generic function definitions it's preferable to use a more descriptive name). There's nothing special about this name, though; most OO programmers were trained using languages that did have a distinguished "self", and have gotten used to thinking that way. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
rick@tetrauk.UUCP (Rick Jones) (04/26/91)
In article <1991Apr23.142800.12215@bony1.bony.com> richieb@bony1.UUCP (Richard Bielak) writes: > >One of the things I liked about "Object Oriented Software Construction" >by B. Meyer, was the idea that a class is both a type and a module. >This idea clears up the confusion as to whether inheritance extends or >specializes. > >When a class is considered to be a type, inheritance specializes the >type. The descendent type is type-compatible with fewer things, so it >is more specialized. > >When a class is considered to be a module, inheritance adds more >routines and attributes. Since the class can do more things it has >been extended. > >I also like the "cleanness" and simplicity of this idea. > >I am curious whether other people think about this, and whether such >"unification" has any disadvantages. I believe it is a powerful notion, and is of course related to the concept of abstract data types. Personally I find that using the principle that a class represents an ADT is the best guide to deciding what the classes should be, and what should go into them. I also add a little of the "responsibility" concept as well. In fact, in the module/type duality, the "type" is really the abstract type rather than the language type. I feel that the current debates about types and type systems are taking an extremely narrow view of the subject. In reality, type conformance is not just about whether an object should "understand the messages", or whatever the metaphor is in the parlance of any particular programming language; this is a language implementor's rather restricted view of the world. For type conformance to be meaningful in terms of the overall design of a program, the semantic effects of each operation applicable to a type need to be consistent as well. This is where the module/type principle really starts to make sense, so that extensions of the module become specialisations of the ADT. Eiffel's inheritance of assertions assures conforming semantics (given that the assertions are used properly), so type conformance contributes towards overall program correctness. In real situations, things are not always so simple, and module extension/specialisation can make certain features of the inherited ADT invalid, so the descendant is not fully type compatible (even seen as an ADT) with its parent - e.g. the infamous polygon/rectangle case. It is, however, conformant in respect of the features which it does support. This is one of the issues which the extended type checking proposed for Eiffel will address. -- Rick Jones, Tetra Ltd. Maidenhead, Berks, UK rick@tetrauk.uucp Any fool can provide a solution - the problem is to understand the problem
jncs@uno.edu (04/26/91)
In article <1991Apr25.074758.6153@jyu.fi>, sakkinen@jyu.fi (Markku Sakkinen) writes: >In article <DAVIS.91Apr24143741@barbes.ilog.fr> davis@barbes.ilog.fr (Harley Davis) writes: >> >>In article <1991Apr23.142800.12215@bony1.bony.com> richieb@bony1.bony.com (Richard Bielak) writes: >> >> One of the things I liked about "Object Oriented Software Construction" >> by B. Meyer, was the idea that a class is both a type and a module. >> ... > >Otherwise, I agree with Davis against the more orthodox view. >Thus, the package/module facilities of e.g. Ada and Modula-2, >when wisely used, are more versatile than the "one type at a time" >approach of CLU (the original ADT language) and most OOPL's. > > >Markku Sakkinen Using the module facilities in Ada and Modula2, I have always been of the mind of using one module to represent one ADT. I have seen examples of modules containing several abstractions, as well as modules inside of modules and I have yet to see what is gained by doing this; I do see what is lost : I cannot not use one of the Abstractions without the others. I see an abstraction as just that, a functional model of data and behavior and as such I want to put it as a library unit. I would like to see examples where the packaging of several abstractions, or the nesting of modules is a proper abstraction modelling. J. Nino Computer Science Department University of New Orleans
mario@cs.man.ac.uk (Mario Wolczko) (04/27/91)
In article <1991Apr23.142800.12215@bony1.bony.com>, richieb@bony1.bony.com (Richard Bielak) writes: > > One of the things I liked about "Object Oriented Software Construction" > by B. Meyer, was the idea that a class is both a type and a module. > This idea clears up the confusion as to whether inheritance extends or > specializes. ... > I also like the "cleanness" and simplicity of this idea. I also like this idea, but unfortunately no existing object-oriented language (to the best of my knowledge) supports it properly. Eiffel, Smalltalk and CLOS all go only half way; C++ is a little better, but still short of the mark. For a class to be a module it should have a clear separation between interface and implementation, such that any compatible reimplementation can be substituted without affecting "users" of that class. That's what module means: you can swap compatible modules with impunity. When the "user" is a client class, most if not all OO languages succeed in hiding implementation, but when the "user" is a subclass, they fail miserably. For example, all of Smalltalk, Eiffel and CLOS allow direct access to all inherited instance variables, so that no part of the internal representation can be hidden. In contrast, C++ lets you declare an instance variable (member) to be private. In none of these languages can you isolate a class from the choice of superclasses made by its parent(s). Mario Wolczko ______ Dept. of Computer Science Internet: mario@cs.man.ac.uk /~ ~\ The University uucp: mcsun!ukc!man.cs!mario ( __ ) Manchester M13 9PL JANET: mario@uk.ac.man.cs `-': :`-' U.K. Tel: +44-61-275 6146 (FAX: 6236) ____; ;_____________the mushroom project___________________________________
jls@rutabaga.Rational.COM (Jim Showalter) (04/30/91)
]>Using the module facilities in Ada and Modula2, I have always been of the mind ]>of using one module to represent one ADT. I have seen examples of modules ]>containing several abstractions, as well as modules inside of modules and I ]>have yet to see what is gained by doing this; I do see what is lost : I cannot ]>not use one of the Abstractions without the others. I see an abstraction as ]>just that, a functional model of data and behavior and as such I want to ]>put it as a library unit. ]> ]>I would like to see examples where the packaging of several abstractions, or ]>the nesting of modules is a proper abstraction modelling. There are numerous occasions when what one is constructing is an abstraction of sufficient complexity that it requires "helper" sub- abstractions. There is no reason to assume that such sub-abstractions have any use outside the immediate implementation: in cases where this is true, placing such sub-abstractions in the library serves no useful purpose, pollutes the namespace, and, in fact, somewhat unbundles the main abstraction being implemented. In such cases, nesting the sub- abstractions inside the main abstraction is clearly a superior approach. Believing that there is necessarily a one-to-one correspondence between abstractions of interest to clients and modules strikes me as simplistic, particularly since the experiences of myself and of numerous customers indicate that this tends often to not be the case. -- * "Beyond 100,000 lines of code, you should probably be coding in Ada." * * - P.J. Plauger, Convener and Secretary of the ANSI C Committee * * * * The opinions expressed herein are my own. *