Xref: utzoo comp.lang.eiffel:1373 comp.object:2503 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!ukc!mucs!logitek!hrc63!mrcu!paj From: paj@mrcu (Paul Johnson) Newsgroups: comp.lang.eiffel,comp.object Subject: Re: Inheritance and Information Hiding Message-ID: <821@puck.mrcu> Date: 4 Feb 91 10:25:30 GMT References: <10612@pasteur.Berkeley.EDU> <485@eiffel.UUCP> <488@eiffel.UUCP> <1991Feb1.015749.10111@Neon.Stanford.EDU> <1081@tetrauk.UUCP> Reply-To: paj@uk.co.gec-mrc (Paul Johnson) Organization: GEC-Marconi Research Centre, Great Baddow, UK Lines: 86 Summary: Expires: Sender: Followup-To: In article <1081@tetrauk.UUCP> rick@tetrauk.UUCP (Rick Jones) writes: >In article <488@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes: >> >> Will anyone take up the simplest example (discussed in my >>posting <485@eiffel.UUCP>): a class POLYGON exists and has >>a procedure ``add_vertex'', which it exports. >>You want to add a class RECTANGLE. What do you do? > > [... Much good stuff deleted ...] > >Has anyone tried to address this problem by considering that a class >essentially has two interfaces? One - the "read" interface - >provides information about the object in its current (abstract) >state. The other - the "write" interface - offers facilities to >change the object. It seems that if the language supported the >ability to define not only the class TYPE of a variable, but also the >class USAGE (read or write), then the restrictions would be clearer, >both to the compiler and to the programmer. It's a little like the >C++ "const" qualifier, but taking the semantic implications a lot >further. > >Eiffel would be well suited to handle this notion, since it already >distinguishes between functions/attributes and procedures. The >concept of declaring an Eiffel reference as "read-only" would simply >prevent it being used to call procedures of the class - only access >to attributes and functions would be allowed (good Eiffel design >avoids the use of functions which have side effects on the the >object's abstract state). This is not a substitute for Bertrand's >more general global type-checking, but would make code clearer in >representing the current use of the object, and catch errors earlier. > >I believe it could also simplify the global typing problem, since >read-only variables would already be limited as to the range of >features available to them, but I haven't had time to consider this >in any depth. Have any of the theorists out there done any work >along these lines? Yes. I have been thinking along precisely these lines and have come up with some ideas which I call "Fine Grain Inheritance". Below is a short summary. I have a couple of papers submitted to `Software -- Practice and Experience' and ECOOP '91. (No offence to the TOOLS '91 people, just a matter of timing). I believe you should split your class up into lots and lots of little superclasses, each implementing one elementary concept (such as "first item" or "read/write current item") and usually having only one or two attributes. Then go through your class heirarchy and split all classes up into "read-only" and "write-only" varients. Then implement them. Don't be frightened of the large amounts of repeated inheritance you wind up with, its OK. Most of your classes will be deferred and you should make all attributes into deferred functions as well, hence allowing them to be either functions or variables in descendant classes. Hence in Dr. Meyer's example, POLYGON will have (amongst others) an ancestor LIST[ VERTEX ], which will have ancestors LIST_READ[ VERTEX ] and LIST_WRITE[ VERTEX ]. RECTANGLE will have (amongst others) an ancestor LIST_READ[ VERTEX_READ ]. Hence not only is it impossible to add or remove verteces of RECTANGLE, it is also impossible to move a vertex (short of reverse assignment). On the other hand a function which needs to enumerate the verteces of a shape will be able to handle both POLYGON and RECTANGLE by taking an argument of type LIST_READ[ VERTEX_READ ]. This scheme becomes completely flexible when a new type rule (which I call the "Sibling-Supertype" rule) is added which (put briefly) allows the following. If the supertypes of A are a subset of the supertypes of B, then A is a supertype of B. These ideas allow the development of totally flexible class libraries. The only problem comes when coarse grain libraries must be reused as well. Of course, tools like "flat" and "short" become absolutely vital in fine grain libraries, as does multiple inheritance. See you all at TOOLS '91. Paul. -- Paul Johnson UUCP: !mcvax!ukc!gec-mrc!paj --------------------------------!-------------------------|------------------- GEC-Marconi Research is not | Telex: 995016 GECRES G | Tel: +44 245 73331 responsible for my opinions. | Inet: paj@uk.co.gec-mrc | Fax: +44 245 75244