Xref: utzoo comp.lang.eiffel:1406 comp.object:2553 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uwm.edu!spool.mu.edu!uunet!mcsun!ukc!mucs!logitek!hrc63!mrcu!paj From: paj@mrcu (Paul Johnson) Newsgroups: comp.lang.eiffel,comp.object Subject: Re: Granularity (was: Inheritance and Information Hiding) Message-ID: <829@puck.mrcu> Date: 11 Feb 91 13:28:07 GMT References: <10612@pasteur.Berkeley.EDU> <485@eiffel.UUCP> <488@eiffel.UUCP> <1991Feb1.015749.10111@Neon.Stanford.EDU> <1081@tetrauk.UUCP> <821@puck.mrcu> <1991Feb6.045542.791@visix.com> <1087@tetrauk.UUCP> Reply-To: paj@uk.co.gec-mrc (Paul Johnson) Organization: GEC-Marconi Research Centre, Great Baddow, UK Lines: 75 Summary: Expires: Sender: Followup-To: In article <1087@tetrauk.UUCP> rick@tetrauk.UUCP (Rick Jones) writes: >In article <821@puck.mrcu> paj@uk.co.gec-mrc (Paul Johnson) writes: >> [...] some ideas which I call "Fine Grain Inheritance" [FGI]. >> >>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. > >I have also wondered whether this is a possible solution. My fear is that you >might end up having to resolve awkward clashes in a complex class which >inherits from very many smaller classes. I haven't been able to try it in >practice, so that is just a gut reaction. This worried me when I first started thinking about the idea. In practice it does not seem to be much of a problem. Name clashes are no more common than in traditional coarse grain libraries because the number of features is not increased, only the number of classes. >>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. > >This I like. It appears a clean way of separating the type hierarchy from the >class hierarchy, which I believe is ultimately at the bottom of this problem. Nice of you to say so. Personally I would have preferred to keep the type and class hierarchies together but I could not think of a clean way to do it. Separating the two makes the subtype graph implicit. Its no longer a heirarchy since two classes A and B can be mutual subtypes via identical parents. Since the subtype graph is the important one for reuse (see below) I would have preferred to make it explicit. On the other hand tools to describe the subtype graph can be built fairly easily. On reuse: when people say "reuse" they usually mean reusing existing code by expanding the classes. In fact this is not particularly powerful. What is needed (and what FGI provides) is a way of avoiding "case-and-paste" reuse where code is copied and then a global search-and-replace is made to some type name. This leads to code bloat and some horrible problems in maintainance. To take our existing example with rectangles and polygons, suppose we need a centre-of-gravity (COG) function for our shapes and for some reason it does not form part of the classes themselves. We have one for polygons "cog( shape: POLYGON );". If in a coarse-grain library we make RECTANGLE a subtype of POLYGON then we can get the cog of a rectangle with no further effort, but we have to trust cog not to change our shapes. For cog that is trivial, but other functions might not respect that and there is no way of statically type checking it. Using FGI, we already have POLYGON_READ, so we make RECTANGLE a subclass of that (and other things, including RECTANGLE_READ and STRETCHABLE). Our cog function we define as "cog(shape:POLYGON_READ)" which guarantees that cog will only read the vertices and not change them. Hence we can reuse cog in a type-safe manner. A problem arises when we have POLYGON but do not have POLYGON_READ. We can construct it out of existing base classes but then POLYGON_READ will not be an ancestor of POLYGON (unless we change POLYGON). The sibling-supertype rule gets around this because the ancestors of POLYGON are a superset of the ancestors of POLYGON_READ. Hence POLYGON is a subtype of POLYGON_READ. 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