From: frank@Cookie.secapl.com (Frank Adams)
Subject: Re: Const Inheritance
Date: Thu, 05 Nov 1992 16:56:58 GMT
Organization: Security APL, Inc.

In article <BwwvMw.DDC@slipknot.rain.com> robert@slipknot.rain.com.UUCP (Robert Reed) writes:
>In article <1992Oct29.173017.109790@Cookie.secapl.com> frank@Cookie.secapl.com (Frank Adams) writes:
>| In article <BwuvIB.B23@slipknot.rain.com> robert@slipknot.rain.com.UUCP (Robert Reed) writes:
>| >In article <1992Oct28.172457.98060@Cookie.secapl.com> frank@Cookie.secapl.com (Frank Adams) writes:
>|>| Assume we have a class Shape, with a subclass Rectangle, and we want to add
>|>| Square as a class.  It seems logical that Square should be a subclass of
>|>| Rectangle.  However, if we make our shapes mutable objects, so that
>|>| Rectangle might have a member function like setWidth(int), this does not
>|>| work.  A Square cannot set its width without simultaneously setting its
>|>| height.
>|>
>|>Not so.  You just have to ensure that the Square class has its own member
>|>function setWidth(int) that constrains the height as well, and similarly with
>|>any setHeight(int) function.
>| 
>| And what do I do with setDimensions(int,int) ?  Not to mention that you have
>| violated the intended semantics of setWidth in the subclass; this is IMHO a
>| mistake.
>
>I have not violated the intended semantics, I have generalized them, within
>reasonable confines of the language.

Since I'm giving the example, I know what the intended semantics are.  If I
am defining the Rectangle class in a context where I can make assertions, I
will assert that setWidth does not change the height, and vice versa.  This
is the intended semantics, even though the assertions are not available in
the language.

>  Now, living within those confines may
>require some redefinition of your planned interface, like the heretofore
>unmentioned setDimensions(int, int).

The class definitions I gave were obviously incomplete; it was implicit that
reasonable additional functions would be available.

In fact, I can define setDimensions as a non-member function completely
outside the class definition:

void setDimensions(Rectangle& r, int x, int y) {
    r.setWidth(x);
    r.setWidth(y);
}

I expect this function to work: after it is called, r.width() should be x,
and r.height() should be y.

>|>  Alternatively, you could make Rectangle a subclass of
>|>Square, define a setPrimaryDimension(int) for Square and add
>|>setSecondaryDimension(int) for the specialized Rectangle class.

There is another problem with this, if I decide to generalize a bit: I may
want to define:

    template<class WidthT, class HeightT>
    class Rectangle {...}

    template<class SideT>
    class Square : public Rectangle<SideT, SideT> {...}

In this case, Rectangle cannot inherit from Square; it would have to change
the types of the instance variables.  This is not an altogether artificial
example; I worked on a word processor (not written in an O.O. language) in
which horizontal and vertical distances were expressed in different units.
(This program had no use for squares, however.)

>| I don't mean to imply that this construct is necessary to create a usable
>| class hierarchy; just that it seems to me to produce a cleaner
>| specification thereof.
>
>That's not all I said in my last note.  My claim was that your language
>enhancement is a partial feature which muddies the specification (by creating an
>artificial restriction on inherited virtual functions to those that are declared
>const), thus complicating the inheritance rules while providing no clear
>advantage.

See my followup to my original article; it provides a point of view under
which the restriction seems natural.