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=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Preventing private procedure visibility being made public through extension Date: Sun, 21 May 2017 10:44:25 +0200 Organization: Aioe.org NNTP Server Message-ID: References: <4a47e4cd-829c-4451-abf1-82cf60b67706@googlegroups.com> NNTP-Posting-Host: BYuA7L7MRjuLLjcoGHOBxw.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.1.1 Content-Language: en-US X-Notice: Filtered by postfilter v. 0.8.2 Xref: news.eternal-september.org comp.lang.ada:46832 Date: 2017-05-21T10:44:25+02:00 List-Id: On 2017-05-21 00:51, Jere wrote: > On Saturday, May 20, 2017 at 4:32:07 PM UTC-4, Dmitry A. Kazakov wrote: >> On 2017-05-20 19:33, Jere wrote: >>> Is there a way for me to prevent extending types from making >>> the procedure public again? >> >> It is public. That was the decision made in the package Base. The >> package Derived has no say on that. >> >> ---------------------------------- >> The actual problem you have is parallel types hierarchies. You want to >> derive tied instances of Base_Type'Class and Base_Param'Class. >> >> Base_Type ----- Base_Param >> | | >> Derived_Type -- Derived_Param >> >> This requires >> >> 1. Full multiple dispatch >> 2. Dispatch constrained to certain combinations (parallel hierarchies) >> >> This is not supported in Ada (or in any other OO language I am aware of) > > If I understand your definitions correctly, C++ supports this. It can > fully dispatch on any number of types since dispatch is tied to the > function and not the type itself. No. Dispatch cannot be tied to anything but a parameter/result (single dispatch) or a combination of (multiple dispatch), just per definition of. In C++ the dispatching parameter is to the first parameter specified in the dotted notation: object.foo(). > I do know that C++ supports hiding of functions by making them private > in the extending class. No. That is not possible in C++ either. A public method cannot be made private. In general from the OO point of view, a method cannot be removed because it is a property of the class and not of an individual type. It is the contract of the class to have a method Foo. All instances of the class must have this method. If they don't they are not instances of. Period. [To support method disallowing the language must support ad-hoc superclasses, so that one could split an original class into parts to chip the undesired operation away from one part and put the new type in that part instead of the whole original class.] > My real issue is with how the constructors for the tagged type in > the library are done. I want my derived type to work with the > constructors defined in the library, which means it has to extend > one of the types defined in the library itself. But I don't want > clients to extend my class and use the inherited constructors from > the base class because they'll break my extended class. These are not constructors proper. Maybe you meant "constructing function". There is a huge difference. Anyway a constructing function being a primitive operation must work, exactly because this is an primitive operation which gets overridden. So works a constructor proper which is not an operation and cannot be called explicitly and when invoked, then implicitly always with its own type. What you have is neither, it is probably an operation to initialize a part of the object. Such things are usually made private [to be used in a public constructing function]. [Yes it is a huge problem for library designers that Ada does not have constructors. Alas, there is no desire to fix that] > My alternate solution was to use composition, but it really feels > inelegant in this case. I did: > > package Derived is > > type Base_Access is access all Base.Base_Type; > > type Derived_Type is tagged limited private; > > procedure Something > (Obj : Derived_Type; > Value : Derived_Param'Class) > is null; > > procedure Get_Access(Obj : Derived_Type) return Base_Access; procedure Get_Access (Obj : Derived_Type) return not null access Base_Type; > private > > type Derived_Type is tagged limited record > Param : Base.Base_Type; Param : aliased Base_Type; > end record; > > end Derived; > > and Get_Access just returns Param'Unchecked_Access. > When I want to use the library methods, I use that to > pass back the correct type for them. > > I really don't like doing this. I don't like using > access types for one. It's also doesn't feel like > a very clean way because you have to do something > out of the ordinary just to use the class like it was > meant to be. Aggregation + delegation is a decent thing. If you used anonymous access you would reduce dangers of pointers to zero. [If Ada supported return by-reference (it existed once in a rudimentary form and was removed in Ada 2005), the construct would be even better.] [If Ada supported interface inheritance, you could inherit interface of Base_Type and use Derived_Type where Base_Type is expected calling to Get_Access implicitly] But wait ... you can still call Something on the Base_Type part of Derived_Type. So, this resolves exactly *nothing*. The problem is in the Base_Type'Class. > The actual use case is Gnoga. All of the constructors > (the Create procedures) require parent to be of type > Gnoga.Gui.Base.Base_Type'Class, but I really want my > Dialog_Type constructor to only accept parents of type > Gnoga.Gui.Window.Window_Type'Class. But it also has > to publicly extend Gnoga.Gui.Base.Base_Type > (or I use Gnoga.Gui.View.View_Base_Type) so that > other controls can create themselves in it. This > opens my type and types that extend it to being > thrashed by calls to Create_From_HTML and so on. > Similar to your suggestion, I can override them and > raise an exception...it just feels clunky. Believe other methods I know and have tried, e.g. involving generics, are far worse. > I was just hoping for something better from a static checking > perspective. There was a discussion in the Gnoga mailing > list if you are wanting more concrete examples. I was just > simplifying it for here to see if there was a language > defined way to get what I needed statically. It sounds like > there isn't. GUI is one of classic examples where multiple dispatch is required. It is a fact of reality which cannot be worked around without compromising something (no pun intended (:-)). -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de