comp.lang.ada
 help / color / mirror / Atom feed
From: Brian May <bam@snoopy.apana.org.au>
Subject: Re: Classwide Parameter?
Date: Tue, 12 Oct 2004 08:53:28 +1000
Date: 2004-10-12T08:53:28+10:00	[thread overview]
Message-ID: <sa4hdp0hno7.fsf@snoopy.apana.org.au> (raw)
In-Reply-To: ckeelg$dkb$05$1@news.t-online.com

>>>>> "matthias" == matthias k <nospam@digitalraid.com> writes:

    matthias> The Shape's Draw method is always called here but it
    matthias> shouldn't. No late binding happens. I have tried to make
    matthias> it abstract, but it didn't even compile then. What's
    matthias> wrong?

Hmmm.. I find it curious that code will even compile. I guess when Ada
has to match a Shape'Class type against these procedures:

    procedure Draw (Obj: Shape'Class);
    procedure Draw (Obj: Circle);
    procedure Draw (Obj: Square);

It isn't ambiguous, even if the shape happens to be a circle or a
square.

I find this case interesting, with your code, too:

procedure Demo is
    C : Circle;
begin
    Draw(C);
end;

Here it replies that the call to draw is ambiguous, because
it doesn't know if it should call:

    procedure Draw (Obj: Shape'Class);

or
    procedure Draw (Obj: Circle);

because both could apply equally.

I found this confusing at first, I would have thought using
"Shape'Class" is the correct way of doing it, as you want explicitly
allow any type of Shape to get passed through. However, this isn't how
Ada supports inheritance.

In order to try and understand how this works better, I once wrote
test code that tested every possible situation. I suggest other
interested people do the same thing. Unfortunately, my hard disk died
since then :-(, but the lessons remained.

Consider the following (dodgy) code:

package Graphics is
    type Shape is abstract tagged null record;
    procedure Draw (Obj: Shape);
    procedure Draw_Class (Obj: Shape'Class);

    type Circle is new Shape with record
       Radius: Float;
       Center: Float;
    end record;
    procedure Draw (Obj: Circle);
    procedure Draw_Class (Obj: Circle);

    type Square is new Shape with record
       Size: Float;
    end record;
end;

My way of "visualizing" the above code (not sure if this is
technically correct), is the compiler sees the "Shape" type, and
associates two methods, "Draw" and "Draw_Class".

The compiler continues, and process the "Circle" class, and sees that
the same two functions have been redefined. Nothing more to do.

It then sees the Square type, and realizes that functions have not
been redefined. As such, it will turn/copy/inherent/whatever this
function:

    procedure Draw (Obj: Shape);

into

    procedure Draw (Obj: Square);

So now you effectively have:

package Graphics is
    type Shape is abstract tagged null record;
    procedure Draw (Obj: Shape);
    procedure Draw_Class (Obj: Shape'Class);

    type Circle is new Shape with record
       Radius: Float;
       Center: Float;
    end record;
    procedure Draw (Obj: Circle);
    procedure Draw_Class (Obj: Circle);

    type Square is new Shape with record
       Size: Float;
    end record;
    procedure Draw (Obj: Square); -- is the same as Draw (Obj: Shape)
end;

It doesn't do the same thing for Draw_Class, perhaps it is clever
enough to realize it isn't needed. So in the above code,
Draw_Class(MyCircle) would be ambiguous, but Draw_Class(MySquare)
wouldn't be.

In summary, there are times you might want to use 'class for procedure
parameters, but not for procedures that can be overloaded in child
types, as the compiler already does everything for you.

Some of my analogies confuse people (instead of making it more clear),
lets hope this helps...
-- 
Brian May <bam@snoopy.apana.org.au>



  parent reply	other threads:[~2004-10-11 22:53 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-11 16:01 Classwide Parameter? matthias_k
2004-10-11 16:53 ` Matthew Heaney
2004-10-11 17:08   ` matthias_k
2004-10-11 19:16     ` Simon Wright
2004-10-11 22:53     ` Brian May [this message]
2004-10-12  2:29     ` Matthew Heaney
2004-10-12  8:01       ` matthias_k
2004-10-12  8:53         ` Martin Krischik
2004-10-12 13:10         ` Matthew Heaney
2004-10-12  7:59     ` Dmitry A. Kazakov
     [not found]       ` <ckg3h6$qau$03$1@news.t-online.com>
2004-10-12  8:14         ` matthias_k
2004-10-12 15:13           ` Dmitry A. Kazakov
2004-10-12  8:10     ` Martin Krischik
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox