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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,ab66185f2bca0483 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2002-11-16 04:39:39 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!canoe.uoregon.edu!logbridge.uoregon.edu!fu-berlin.de!uni-berlin.de!dialin-145-254-039-183.arcor-ip.NET!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Extension of non-limited type needs limited component Date: Sat, 16 Nov 2002 13:39:18 +0100 Organization: At home Message-ID: References: <2dbd76f3.0211130203.7d2d14fd@posting.google.com> <2dbd76f3.0211140126.5d233e41@posting.google.com> <3vb7tug4h99mmalcn0l5ul18cu0ui6i458@4ax.com> Reply-To: mailbox@dmitry-kazakov.de NNTP-Posting-Host: dialin-145-254-039-183.arcor-ip.net (145.254.39.183) Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7Bit X-Trace: fu-berlin.de 1037450378 16028236 145.254.39.183 (16 [77047]) User-Agent: KNode/0.7.1 Xref: archiver1.google.com comp.lang.ada:30981 Date: 2002-11-16T13:39:18+01:00 List-Id: Robert A Duff wrote: > Dmitry A. Kazakov writes: > >> On Fri, 15 Nov 2002 00:30:03 GMT, Robert A Duff >> wrote: >> >> >Dmitry A. Kazakov writes: > >> Sure? And what about this: >> >> type A is tagged ... >> procedure Foo (L, R : A); >> >> type B is new A with .... >> >> X : A'Class := Some_A; >> Y : A'Class := Some_B; >> >> Foo (X, Y); -- Oops, dispatching to nowhere! > > True. But I'm not happy about it. And it doesn't mean single-argument > dispatching should be made more dangerous to match double-arg > dispatching. ;-) Of course not. However there is a difference. My example can be cured by introducing multiple dispatch. The case when Circle is derived from Ellipse and Resize (E : in out Ellipse; X_Size, Y_Size : Distance) has to be disallowed cannot be cured at all. >> Further one can always override with a subroutine that throws >> Program_Error. Is that better? IMO it is the same. > > Yes, it is the same. I see no reason to add special syntax to make it > easy, though. 1. Earlier error detection. If you disallow an operation, then in a statical case, you will get a compile-time error 2. Getting rid of overloading contaminations > Note that Java more-or-less prevents this problem by making exceptions > part of the visible contract. I think they got some of the details > wrong, but they are on the right track. The Java rules are a pain, > but I think they could be modified to make them work nicely. I agree. While developing large programs, tracking down the exceptions becomes a real pain. I have no idea how to do it properly, but surely the exceptions should be a part of the contract and another important thing, there should be a way to somehow tell to "exception when =>", what is the full list of the alternatives, so that it could work as safe as "case ... when =>" does. >>... The only real >> difference is that one cannot get rid of overloading of the undesired >> operation. What is actually required. I think that there could be >> situations where it would be useful to disallow an operation in the >> public interface and to override it with something working in the >> private one. > > Hmm. What example? It seems to me that hiding/disallowing the > operation for the derived type is dishonest, because a client can always > call that operation by converting to the parent type 'Class and > dispatching. Ah, that is re-dispatch, it is a vicious thing. I wished it to be removed from Ada. Converting to Parent'Class should be more than just view change, at least in case of disallowing => breaking Parent's contract. It means that the result of Parent'Class (A_Child) should a NEW object which is really of Parent type and, lo, you can safely dispatch to any operation of Parent! > Note that you can say: > > type T is new A with private; > ... > type T is new B with record... > > where B is derived from A, and has more operations. > This is a useful capability, and is similar to what you asked for above. > The "more operations" are visible only inside T package. > Clients can't convert to B, because they can't see that T is "really" > derived from B. > > Here's an idea I've been thinking about for some years, which might > address your desire to "take away" operations: > Define two kinds of inheritance, "is a" inheritance, and "is like a" > inheritance. When you use "is a" inheritance, you can only *add* > operations, and you can convert to the parent type. When you use "is > like a" inheritance, you can also take away operations, but you are > forbidden from converting to the parent type. With "is like a" > inheritance, you are defining a new abstraction that is similar to > the parent, but you don't claim that it "is a" parent, and you don't > want to view the new type *as* a parent. What do you think? It looks very close to my understanding of the problem. Your "is a" inheritance is one when we inherit both the contract and the implementation of the parent type, i.e. we extend it. This is a sort of LSP-subtyping, however, not enforced. "is like a" inheritance is when we inherit only the contract (at least in the public part, in the private part it could be still "is a"). For instance, let I have the type String, if I derive from it by "is like a", then I am absolutely free to implement it as a record. Then you say that conversion to parent should be forbidden. Why? Because the compiler has no clue how to do it? So let's make it a part of the contract. I.e. if I derive My_String from String, I should also provide My_String->String conversion, if I wish to access in-methods of String. I should define My_String<-String if I wish to access out-methods of String. I should define both if I wish to access everything. -- Regards, Dmitry A. Kazakov www.dmitry-kazakov.de