From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,8047848c4805a99e X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit From: Brian May Newsgroups: comp.lang.ada Subject: Re: Classwide Parameter? References: Date: Tue, 12 Oct 2004 08:53:28 +1000 Message-ID: User-Agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux) Cancel-Lock: sha1:+AZt9lNnZUelFabYcSXxpSeATQQ= MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii NNTP-Posting-Host: dsl-202-173-153-89.vic.westnet.com.au X-Trace: news.melbourne.pipenetworks.com 1097535196 202.173.153.89 (12 Oct 2004 08:53:16 +1000) X-Complaints-To: abuse@pipenetworks.com X-Abuse-Info: Please forward all headers to enable your complaint to be properly processed. Path: g2news1.google.com!news1.google.com!news.glorb.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newshosting.com!nx01.iad01.newshosting.com!uunet!dca.uu.net!snewsf0.syd.ops.aspac.uu.net!news1.optus.net.au!optus!news.mel.connect.com.au!news-north.connect.com.au!news.alphalink.com.au!news.melbourne.pipenetworks.com!not-for-mail Xref: g2news1.google.com comp.lang.ada:5056 Date: 2004-10-12T08:53:28+10:00 List-Id: >>>>> "matthias" == matthias k 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