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,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.107.3.225 with SMTP id e94mr11121602ioi.7.1519742093357; Tue, 27 Feb 2018 06:34:53 -0800 (PST) X-Received: by 10.157.3.237 with SMTP id f100mr653590otf.6.1519742093178; Tue, 27 Feb 2018 06:34:53 -0800 (PST) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!news.uzoreto.com!weretis.net!feeder6.news.weretis.net!feeder.usenetexpress.com!feeder-in1.iad1.usenetexpress.com!border1.nntp.dca1.giganews.com!nntp.giganews.com!o66no248002ita.0!news-out.google.com!a2ni825ite.0!nntp.google.com!o66no247998ita.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Tue, 27 Feb 2018 06:34:52 -0800 (PST) In-Reply-To: <473f9b1a-6466-4745-9041-107f54062cf2@googlegroups.com> Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=71.171.117.31; posting-account=QF6XPQoAAABce2NyPxxDAaKdAkN6RgAf NNTP-Posting-Host: 71.171.117.31 References: <62f83fe5-15d6-41cf-952f-bc3cb077d42f@googlegroups.com> <473f9b1a-6466-4745-9041-107f54062cf2@googlegroups.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: Subject: Re: [Newbie] doubly constrained array, dumb question From: Jere Injection-Date: Tue, 27 Feb 2018 14:34:53 +0000 Content-Type: text/plain; charset="UTF-8" Xref: reader02.eternal-september.org comp.lang.ada:50681 Date: 2018-02-27T06:34:52-08:00 List-Id: On Monday, February 26, 2018 at 8:29:17 PM UTC-5, Mehdi Saada wrote: > > Dmitry said: > > 1. array's index > > 2. array's element > > 3. record's component > > 4. access type's target type > > 5. discriminant > > 6. argument of a subroutine access type > > 7. class-wide types (closed range of descendants T'Class (T..S)) > > 8. tagged type primitive operations (disallowing operations) > > 9. protected and task type entries (disallowing operations) > > 10. task type entry family > > For 8: a class has any sense at all only if there's no dispatching to an inexistent method, and your forbidding some methods would do the same, raise an exception. > So to avoid that, if you want to disallow operations (without make a dispatching call to it raises an exception), you have to cut the tagged type from its root, by hiding the fact it has a parent type, so as to disinherit the parent's method. > If you don't want that, (I suppose) one would have to implement a per-operation basis dispatching mechanism with a list of allowed types for each methods ? > Two other options: 1. Full composition with switch statements (which is akin to that last sentence I quoted). 2. The Rust inheritance model, which is a bit more complex. I've been dorking around with Rust some and while I don't like all the language has to offer, it's inheritance model is intriguing. Basically, you implement type extension purely through composition. Normally, this would force you to use switch statements, etc to emulate dispatching, but in Rust, they allow you to implement interfaces (or traits as Rust calls them). So the design idea is anything that you actually want to dispatch on is relegated to an interface (or multiple interfaces), and you use classwide types of the interface to do the dispatching. This makes for what is practically a max 1 level deep extension tree. Composition allows for you to hide non dispatching operations as you see fit (I.E. you only implement the ones you want your client to see) while the interfaces allow you to cleanly dispatch for operations. You are also free to only implement the interfaces you want for each level of inheritance. So parent classes can implement interfaces that child classes do not. I'm not saying this is the end all be all method, but it is definitely interesting to tinker with and makes you consider designs a bit differently (much like pure composition does). Example: ********************************************************************* with Ada.Text_IO; use Ada.Text_IO; procedure jdoodle is ------------------------------------------------------------------------ -- This provides the interface for some dispatchable process -- along with a default implementation (optional). -- package Dispatching is type Dispatchable1 is limited interface; procedure Do_Something(Self : Dispatchable1) is abstract; type Default_Dispatchable1 is new Dispatchable1 with null record; overriding procedure Do_Something(Self : Default_Dispatchable1); type Dispatchable2 is limited interface; procedure Do_Another(Self : Dispatchable2) is abstract; end Dispatching; package body Dispatching is procedure Do_Something(Self : Default_Dispatchable1) is begin Put_Line("Default Dispatching"); end Do_Something; end Dispatching; ------------------------------------------------------------------------ -- This is the base class which implements some dispatchable process -- use Dispatching; package Base is type Instance is new Dispatchable1 and Dispatchable2 with private; overriding procedure Do_Something(Self : Instance) with Inline; overriding procedure Do_Another(Self : Instance); not overriding procedure Other_Op(Self : Instance); private type Instance is new Dispatchable1 and Dispatchable2 with record Parent : Default_Dispatchable1; -- Composition end record; end Base; package body Base is procedure Do_Something(Self : Instance) is begin Put("Base Dispatching => "); Self.Parent.Do_Something; end Do_Something; procedure Do_Another(Self : Instance) is begin Put_Line("Another Dispatching"); end Do_Another; procedure Other_Op(Self : Instance) is begin Put_Line("Some other op"); end Other_Op; end Base; ------------------------------------------------------------------------ -- This is a derived class which implements some dispatchable process -- Inheritance is done through composition. Note that it does -- not proved Other_Op -- package Derived is type Instance is new Dispatchable1 with private; overriding procedure Do_Something(Self : Instance) with Inline; private type Instance is new Dispatchable1 with record Parent : Base.Instance; -- Composition end record; end Derived; package body Derived is procedure Do_Something(Self : Instance) is begin Put("Derived Dispatching => "); Self.Parent.Do_Something; end Do_Something; end Derived; ------------------------------------------------------------------------ -- Some local variables to test with -- v1 : Base.Instance; v2 : Derived.Instance; ----------------------------------------------------------------------- -- Dispatching calls all handled through interface classwide types -- procedure Some_Function_Call(Object : Dispatchable1'Class) is begin Object.Do_Something; end Some_Function_Call; procedure Some_Other_Call(Object : Dispatchable2'Class) is begin Object.Do_Another; end Some_Other_Call; begin Put_Line("Starting"); Some_Function_Call(v1); Some_Function_Call(v2); Some_Other_Call(v1); --Some_Other_Call(v2); -- would raise a compiler error end jdoodle;