From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: run-time type checking)
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Sat, 15 Aug 1992 18:23:04 GMT

In article <713823917snx@trmphrst.demon.co.uk> nikki@trmphrst.demon.co.uk (Nikki Locke) writes:
>
>In article <4820@holden.lulea.trab.se> jbn@lulea.trab.se (Johan Bengtsson) writes:
>
>> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>> :
>> :There are other ways than tagged pointers to make downcasting
>> :sound. One might be to declare the derived classes that you want
>> :to downcast to in the base class FROM which you want to downcast:
>> :	class Base { //....
>> :		operator Derived1*() =0;
>> :		operator Derived2*() =0;
>> :	};
>> :Now what does this do? Well, it preserved th open/closed principle
>> :and encapsulation and the explicit interfaces principle.
>> 
>> What if someone using your classes decides to add a Derived3 class
>> to which downcasting should be possible?  He must modifiy your
>> class Base, for which he may not have source code.
>> 
>> Does not (help) preserve the open/closed principle at all, IMHO.
>Perhaps I misunderstand the meaning of the "open/closed principle", but I 
>understood that it implies that every operation which can be applied to an
>object through a reference or pointer to a Base class should be visible in 
>the Base class declaration. 

	Actually, Meyer calls that the Explicit Interfaces Principle.
A module is closed if it is available for use (finished, compiled,
stored in a library). A module is open if it can be extended
(new fields added, new functions defined, old functions restricted)
The open/closed principle states a module should be both open and
closed. The mechanism of inheritance and virtual functions, that is,
having classes as modules, satifies these criteria. And as we know,
these are what give us polymorphism, in other words, the open/closed
principle is what gives us polymorphism.


	Note it is possible to close the interface to a class
separately from the class itself. (others can compile but not
yet link the class).

>An excellent example was presented earlier in 
>this thread (but I have expired it, so I'll have to make up a new one).
>
>class Base {
>protected:
>	int i;
>public:
>	int get() const { return i; }
>	};
>
>class Derived {
>public:
>	void set(int j) { i = j; }
>	};
>
>Now, if downcasting is not allowed, we can guarantee that any operation on
>a Base pointer or reference will not modify i. I understood this to be one
>of the requirements of the open/closed principle.

	Actually, whats broken directly seems to be Explicit interfaces
principle, and also the Information hiding principle--encapsulation
is violated. What violated indirectly is the openness of the base
class to arbitrary extensions, because Derived is a *special*
extension in that downcasting to it is allowed. So the Base class
isn't really open, because it isn't open to arbitrary extension.

	As you know from mathematics, to prove something for
ALL cases it suffices to prove it for a single ARBITRARY case.
ARBITRARY means in particular not relying on any special
properties of that case: it means doing it for the abstract case.

	Thus in a sense, arbitrary means all means unbounded.
No limits or restrictions. And the lack of restriction
on what you can derive is obtained precisely from the
restriction that you must stick to the abstract interface
of the base. (That means the semantics cant be changed
in other ways either, ways the compiler could never enforce).

	As soon as you can downcast arbitrarily, without
constraint, then EVERY derived class can be made special.
Where is polymorphism then? It is gone.
>
>As soon as you allow downcasting to class Derived, i may be modified. This
>violates (what I understand to be) the principle.
>
>Of course, if you state clearly in the declaration of Base that it may be 
>converted into a Derived, you are also stating that i may be modified 
>through a Base pointer/reference.

	By making the ability to downcast Explicit in the interface
of the base class, the closure of the base now depends on the listed
derived classes too, so it is then open (excepting the named derived classes).

>
>The original poster suggested that some new syntax be invented to state 
>this intention. Max's post explained (albeit with a slightly incorrect 
>example :-) that no new syntax was needed, just a few (virtual) functions 
>in the Base class.

	No, probably new syntax would be used. The point was to demonstrate
that using existing technology you can downcast already but with the
restriction you have to declare the classes you're downcasting TO.
And that that is sound (because it uses existing sound type safe nice
C++ technology). I claim this restriction is required in some form
to preserve open/closed principle, that is, to preserve polymorphism.

>
>Corrections of any incorrect understanding on my part welcome.


	Another method is to use tagged pointers. ALL these methods
suffer from lack of extensibility that downcasting doesn't. Thats
because there is only ONE method of extensibility that is sound,
and we already have it. Polymorphism. Virtual functions.

	BTW: I could easily be wrong. But I'm just not convinced.
The example code above shows the issue clearer than 1000 lines
of argument :-)

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Newsgroups: comp.lang.c++