comp.lang.ada
 help / color / mirror / Atom feed
From: Jere <jhb.chat@gmail.com>
Subject: Re: Preventing private procedure visibility being made public through extension
Date: Sun, 21 May 2017 13:06:34 -0700 (PDT)
Date: 2017-05-21T13:06:34-07:00	[thread overview]
Message-ID: <9cdf04e6-123e-4bd9-b466-77aad00d61bb@googlegroups.com> (raw)
In-Reply-To: <ofrk18$s6f$1@gioia.aioe.org>

On Sunday, May 21, 2017 at 4:44:27 AM UTC-4, Dmitry A. Kazakov wrote:
> 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:
> > 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.]
> 
The language supports making them private in the context of the
extending classes.  Take for example:

class Base{
public:
   class Base_Param{};

   void Something(Base_Param Obj){}

};

class Derived : public Base {
private:

   void Something(Base_Param Obj); 
};

class MoreDerived : public Derived{};

The following will not compile:
void run_test(){
   Base::Base_Param b;
   Derived d;

   d.Something(b);
}

nor will
void run_test(){
   Base::Base_Param b;
   MoreDerived m;

   m.Something(b);
}

both will fail with the error: "Something" is a private member of Derived

I'm not saying it is the right design, but it is possible.  You can
always get around it by casting down to type Base (where the function
is public), but that is an explicit action that takes intent.  A 
user just creating a type can't use the function out of the box
because, as the error indicates, it is private for Derived (and
for MoreDerived by extension).

> > 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]

You're right, they are not proper constructors.  I haven't found 
anything in Ada yet that gives me that.  At best they are 
initializers.

> > 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.
> 
Definitely.  I am also worried about someone copying the access
value and holding onto it past the lifetime of the object. I try
to avoid Access types when I can.  I wish there was someway to
actually pass a limited type as a function return that didn't
involve build in place that can initialize.  I just want to be
able to return the limited object out temporarily to access it:

Derived.Get_Base.Some_Procedure

but not allow initialization when I don't intend the function
to do that:

Temp : Base := Derived.Get_Base;  -- didn't really want to allow

As it stands the only option I came up with is something 
kludgy like:

type Derived_Public is tagged limited record
   Parent : Base_Type;
end record;

-- This is the workhorse type
type Derived is new Derived_Public with private;

-- This type is purely for constructor like procedures
type Derived_With_Constructors is 
   new Derived with private;

procedure Constructing_Procedure
   (Obj : in out Derived_With_Constructors);
   
Then people extending it just have to do:

   type More_Derived is new Derived with private;
private
   type More_Derived is new Derived_With_Constructors 
   with null record;

That way, extenders don't publicly provide the Constructor
procedures, but have access to them privately.  Additionally,
I get the Base type via composition so it's procedures won't
stomp on Derived types and I can still use it in the library.

There's probably a better way, but that is what I came up
with.  I don't like it though.

> > 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.
That's been my experience as well.

 
> > 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 (:-)).
> 
Thanks for the responses!


  parent reply	other threads:[~2017-05-21 20:06 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
2017-05-21 12:19       ` J-P. Rosen
2017-05-21 12:53         ` Dmitry A. Kazakov
2017-05-21 20:06       ` Jere [this message]
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