comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Preventing private procedure visibility being made public through extension
Date: Sun, 21 May 2017 10:44:25 +0200
Date: 2017-05-21T10:44:25+02:00	[thread overview]
Message-ID: <ofrk18$s6f$1@gioia.aioe.org> (raw)
In-Reply-To: 4a47e4cd-829c-4451-abf1-82cf60b67706@googlegroups.com

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

  parent reply	other threads:[~2017-05-21  8:44 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-20 17:33 Preventing private procedure visibility being made public through extension Jere
2017-05-20 20:13 ` AdaMagica
2017-05-20 21:55   ` Jere
2017-05-20 20:32 ` Dmitry A. Kazakov
2017-05-20 22:51   ` Jere
2017-05-21  0:51     ` Jere
2017-05-21  9:16       ` Chris Moore
2017-05-21 22:55         ` Jere
2017-05-21  8:44     ` Dmitry A. Kazakov [this message]
2017-05-21 12:19       ` J-P. Rosen
2017-05-21 12:53         ` Dmitry A. Kazakov
2017-05-21 20:06       ` Jere
2017-05-21 21:07         ` Dmitry A. Kazakov
2017-05-21 22:28           ` Jere
2017-05-22  8:52             ` Dmitry A. Kazakov
2017-05-22 13:33               ` AdaMagica
2017-05-22 13:43           ` AdaMagica
2017-05-22 21:17         ` Randy Brukardt
2017-05-25  4:06           ` Jere
2017-05-25 19:39             ` Randy Brukardt
2017-05-25 22:53               ` Jere
2017-05-25 22:57                 ` Jere
2017-05-26 20:46                 ` Randy Brukardt
2017-05-26 22:35                   ` Simon Wright
2018-05-20 11:22                     ` Simon Wright
2018-05-20 12:03                       ` Jere
2017-05-26 22:58                   ` Jeffrey R. Carter
2017-05-30 21:15                     ` Randy Brukardt
2017-06-02  1:07                       ` Jere
2017-06-02  7:31                         ` Dmitry A. Kazakov
2017-06-02  8:09                         ` Mark Lorenzen
2017-06-02 11:31                         ` Simon Wright
2017-05-22 21:12   ` Randy Brukardt
2017-05-23  7:38     ` Dmitry A. Kazakov
2017-05-21 18:14 ` Robert Eachus
2017-05-21 20:21   ` Jere
2017-05-21 21:09     ` Jeffrey R. Carter
2017-05-21 22:46       ` Jere
2017-05-22 21:24         ` Jeffrey R. Carter
2017-05-25  3:45           ` Jere
2017-05-21 21:20     ` Dmitry A. Kazakov
2017-05-21 21:45       ` Jere
replies disabled

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