From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: run-time type checking (was: Re: Covariant Types in Derived Classes)
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Sat, 25 Jul 1992 17:20:45 GMT

In article <1992Jul24.234628.21196@cadsun.corp.mot.com> shang@corp.mot.com writes:
>> >(John MAX Skaller) writes: 
>>We design our systems properly in the first place, and then the need
>>to downcast never arises, when our thoughts wander in that 
>>direction one can be sure we are not thinking virtuously,
>>and perhaps the design itself is flawed.
>> ....
>
>In article <1992Jul24.143359.3602@advtech.uswest.com> glw@io.uswest.com (Glenn  
>Williams) replies:
>>
>> You have stated all this before, and every time you do, you fail to provide
>> any examples of how you would design without downcasting. 
>> 
>> So, as I asked for earlier, let's have an example of a properly
>> designed system.
>> 
>Indeed. Whenever I gave an example that demostrates the necessity of downcast,  
>I was always considered to introduce a bad design, but I never get an example  
>which is considered good and can solve the specific problem shown by my  
>example. So, before blaming the "bad", show the good please.

	I am working on one. I did give a skeletal outline here
on my reply bu the !@#$%^&*() (sorry) system logged me out,
and this is the second attempt.

>
>Here, I'd like to use the example given by John's own:
>
>> >(John MAX Skaller) writes: 
>> >class Animal {
>> >	int mate(Animal&);
>> >};
>> >class Dog : Animal {
>> >	int mate (Animal&);
>> >};
>> 
>> >We REALLY want Dog::mate(Dog&), but we can't have it.
>>
>
>Therefore you need RTTI and downcast, 

	No, we dont. I stuffed up the design. (I can do it too :-)

>though a little bit too late to check the  
>validation within the method body:
>
>class Dog : Animal
>{     int mate (Animal& a)
>      { if (typeof(a) != Dog) return an_error_code;
>        ...
>      };
>}

	OK. My design is flawed. Why? Because I didnt write the
spec properly.

	Spec1: All animals can have a go at mating.
	If they are of one species (and opposite sex) then
	the female is flagged as pregnant.

This spec REQUIRES the interface:

	void Animal::mate(Animal&);

because the spec says 'All animals can have a go at mating'.

To check if the animals are of the same type, I provide
type information:

	virtual char* Animal::Species()=0;

and the sex:

	enum {male,female,infertile} sex;

Now I can write:

	void Animal::mate(Animal& x)
	{
		if(sex==infertile || x.sex==infertile)return;
		if(strcmp(Species(),x.Species())) return;
		if(sex==x.sex)return;
		if(sex==female) pregnant=TRUE;
		else x.mate(*this);
	}

NOW: I want to demonstrate why using RTTI is WRONG in this case,
and why the Species() function is required.	


The demonstration is so simple, and applies so generally, I wonder
why I didnt think of it before.

	class DOG : Animal { ....
	class HUND : Animal { .. // german programmer

See: BOTH classes are IMPLEMENTATIONS of the very same animal
species. But their exact types are different.
So they could never mate. Tell that to German Shepard
and an Alsatian :-)


[Note: I answer the other bits of your post in my previous
attempt butgot logged out, this time I will just have to
pass. For the moment :-)

-- 
;----------------------------------------------------------------------
        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++