comp.lang.ada
 help / color / mirror / Atom feed
* Mixing public and private member of a class. Dealing with what to hide and not
@ 2019-02-13 17:40 Daniel Norber
  2019-02-13 17:46 ` Daniel
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Daniel Norber @ 2019-02-13 17:40 UTC (permalink / raw)


Sorry for my bad english.
I'm having big troubles in how Ada deals mixing public and private member of a class. 

Please someone can help how to do it using Ada ?

Im building lets say a library, where i choose to use classes (tagged types) for interfacing with the outer world.

This library is organized in services using ada packages.

Lets say my Library is called SERVICES and it has differents parts, for example massaging service and making pizzas service. Every services goes in a differente child package, but i will focus just in massaging service package.

I had two approaches. One trying to build classes in the same package and i always get "premature 
derivation of derived or private type", so i will explain how i try using differents tagged in different packages paradigm.

As i understood, the only way to mix public and private members is declaring the public part and make a child with private;

Here is my code:

package SERVICES is
pragma PURE;
end SERVICES;

-having 1 dependency with my internal code:
with REGISTERING_STUFF;
package SERVICES.MASSAGES is
   type dont_instance_me_bcs_im_not_full_but_public is record
       Register : REGISTERING_STUFF.notebook;
   end record

   type instance_bcs_im_the_good is new dont_instance_me_bcs_im_not_full_but_public with private;

   --public part for the outer world:
   procedure makeme_a_massage_in_public (S: instance_bcs_im_the_good);
   function Say_in_public_if_its_painfull(S:instance_bcs_im_the_good) return boolean;

private

   --private part for my massaging related code
   type instance_me_bcs_im_the_good is new dont_instance_me_bcs_im_not_full  with record
      more_secret_data  : natural;
   end record;
   procedure changemysecrets (S: instance_me_bcs_im_the_good);
end SERVICES.MASSAGES;


package REGISTERING_STUFF is
   type notebook is tagged limited private;
   function whoami (S: notebook) return String;

private

   type notebook is tagged record
      private_secret_data : natural;
   end record;
   procedure takecarechangingnotes (S: notebook ;data: String); 
end REGISTERING_STUFF;


So from a client to the library, i try this:


--The client only Have 1 dependency with my library
with SERVICES.MASSAGES;

package client body is

  interface_class : SERVICES.MASSAGES.instance_me_bcs_im_the_good;

begin

  ada.text_io.Put_Line(interface_class.Register.whoami);

end client;


I have the next error running client:
>error  no selector whoami for private type notebook


I want one and simple class that includes everything to the outer world like "instance_me_bcs_im_the_good" that expose the public part like procedure "makeme_a_massage_in_public", and also the public part of "notebook" like "whoami" function, but hidding for example takecarechangingnotes just for internal use . In the same way this whole class has private parts like "changemysecrets" not available for the outer world.

Any help or ideas of how to do it? (if it possible respecting 1 "with" dependency in the outter world side)

Thank you very much and Best regards.














^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Mixing public and private member of a class. Dealing with what to hide and not
  2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
@ 2019-02-13 17:46 ` Daniel
  2019-02-13 20:05 ` Dmitry A. Kazakov
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Daniel @ 2019-02-13 17:46 UTC (permalink / raw)


sorry, i've forgot writing fast: every type in the example is suposed to be tagged

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Mixing public and private member of a class. Dealing with what to hide and not
  2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
  2019-02-13 17:46 ` Daniel
@ 2019-02-13 20:05 ` Dmitry A. Kazakov
  2019-02-13 20:39 ` J-P. Rosen
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry A. Kazakov @ 2019-02-13 20:05 UTC (permalink / raw)


On 2019-02-13 18:40, Daniel Norber wrote:
> Sorry for my bad english.
> I'm having big troubles in how Ada deals mixing public and private member of a class.

Well, this one of sore spots in Ada where information hiding does not 
work well. Anyway, try this:

    type T is abstract tagged record -- This is a helper type, no
       Public : Integer;             -- instances of
    end record;
    type S is new T with private; -- This is the interface type
private
    type S is new T with record
       Secret : Integer;
    end record;

P.S. In many cases you do not expose members, only operations.

P.P.S. Discriminants can be misused as read-only members:

    type S (Public : Integer) is new T with private;
private
    type S (Public : Integer) is new T with record
       Secret : Integer;
    end record;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Mixing public and private member of a class. Dealing with what to hide and not
  2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
  2019-02-13 17:46 ` Daniel
  2019-02-13 20:05 ` Dmitry A. Kazakov
@ 2019-02-13 20:39 ` J-P. Rosen
  2019-02-14  0:21 ` Jere
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: J-P. Rosen @ 2019-02-13 20:39 UTC (permalink / raw)


Le 13/02/2019 à 18:40, Daniel Norber a écrit :
> I'm having big troubles in how Ada deals mixing public and private member of a class. 
> 
I'm not sure if this is really your problem, but since you are new to
Ada, let me explain this.

In Ada, the fundamental building block is the type. Every property is
attached to a type. Unlike C++, being public or private is not a
property of a member, but a property of the member's type. Hence you can do:

package Pack is
    type Secret_Data is private;
    type Instance is tagged
       record
          My_Public: Some_Public_Type;
          My_Secret: Secret_Data;
       end record;
    ...

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Mixing public and private member of a class. Dealing with what to hide and not
  2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
                   ` (2 preceding siblings ...)
  2019-02-13 20:39 ` J-P. Rosen
@ 2019-02-14  0:21 ` Jere
  2019-02-14 18:04 ` G.B.
  2019-02-22  8:42 ` Daniel
  5 siblings, 0 replies; 7+ messages in thread
From: Jere @ 2019-02-14  0:21 UTC (permalink / raw)


On Wednesday, February 13, 2019 at 12:40:24 PM UTC-5, Daniel wrote:
> <SNIPPED>
> 
> Any help or ideas of how to do it? (if it possible respecting 1 "with" dependency in the outter world side)
> 
> Thank you very much and Best regards.

After fixing syntax errors, the example you gave compiled fine in 
GCC 7.1.1 (there were quite a few syntax errors however).

That said, I'm not a fan of the two stage extension method.  I prefer
one of two ways (depending on if the "public" component is limited or
not:

1.  Non-limited built in components:  I just make them private but
use getter and setter functions with the same name as the component.

2.  Complex or limited components:  I use "reference types" to get 
access to them.  In order to make this work, the record component 
needs to be aliased.  I'll give an example of this below.  I'm using
simple built in types for the example, but hopefully you can 
extrapolate the example to types like your notebook type.

EXAMPLE:
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is

    package Thing is
        type Instance is tagged limited private;
        subtype Class is Instance'Class;
        
        -- This defines a reference type for a 
        -- component that can be modified by
        -- a client package
        type Natural_Holder
            (Element : not null access Natural)
        is limited null record
            with Implicit_Dereference => Element;
        
        -- This function returns that reference
        -- type.  Notice the name of the function
        -- matches the field (not required, but
        -- I like this nomenclature)
        function Value
            (Self : aliased in out Instance) 
             return Natural_Holder;
             
        -- This defines a reference type for a 
        -- component that cannot be modified by
        -- a client package.  It is essentially
        -- constant
        type Constant_Character_Holder
            (Element : not null access constant Character)
        is limited null record
            with Implicit_Dereference => Element;
            
        -- This function returns that reference
        -- type.  Notice the name of the function
        -- matches the field (not required, but
        -- I like this nomenclature)
        function Constant_Value
            (Self : aliased Instance)
             return Constant_Character_Holder;
        
    private
    
        type Instance is tagged limited record
            Value          : aliased Natural   := 0;
            Constant_Value : aliased Character := 'W';
        end record;
        
        function Value
            (Self : aliased in out Instance) 
             return Natural_Holder
        is (Element => Self.Value'Access);
        
        function Constant_Value
            (Self : aliased Instance)
             return Constant_Character_Holder
        is (Element => Self.Constant_Value'Access);
        
    end Thing; 
    
    Something : Thing.Instance;

begin
    Put_Line("Value ="  & Natural'Image(Something.Value));
    Something.Value := 23;
    Put_Line("Value ="  & Natural'Image(Something.Value));
    
    Put_Line("Constant_Value ="  
             & Character'Image(Something.Constant_Value));
             
    -- Fails to compile next line since the value is constant       
    --Something.Constant_Value := 'C';
    
end Hello;

RM section on user defined references:
http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-1-5.html#I2450

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Mixing public and private member of a class. Dealing with what to hide and not
  2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
                   ` (3 preceding siblings ...)
  2019-02-14  0:21 ` Jere
@ 2019-02-14 18:04 ` G.B.
  2019-02-22  8:42 ` Daniel
  5 siblings, 0 replies; 7+ messages in thread
From: G.B. @ 2019-02-14 18:04 UTC (permalink / raw)


On 13.02.19 18:40, Daniel Norber wrote:
> I'm having big troubles in how Ada deals mixing public and private member of a class.

The easiest way out is to always structure Ada types as if you'd write

class AdaStyle {
private:
    int data;
    T0* thing;
public:
    int query(...) const; // involves `data`
    virtual void merge(const T0& other);
};

I.e., as others have said, just don't make any data compotent publicly
accessible. A possible exception might be a read-only "initialization
parameter" such as is offered by a discriminant:

    type Thing (Capacity : Natural) is private;

    type Pixel (Color : RGB) is limited private;

These can freeze numbers of parts of variants of (record) types.
Some suggest to also consider composition as a possible alternative
to extension. So does Stroustrup, IIRC.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Mixing public and private member of a class. Dealing with what to hide and not
  2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
                   ` (4 preceding siblings ...)
  2019-02-14 18:04 ` G.B.
@ 2019-02-22  8:42 ` Daniel
  5 siblings, 0 replies; 7+ messages in thread
From: Daniel @ 2019-02-22  8:42 UTC (permalink / raw)


Thank you everyone for the help.
I can go ahead taking some ideas people propose here.
This is a really helpful group.


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-02-22  8:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-13 17:40 Mixing public and private member of a class. Dealing with what to hide and not Daniel Norber
2019-02-13 17:46 ` Daniel
2019-02-13 20:05 ` Dmitry A. Kazakov
2019-02-13 20:39 ` J-P. Rosen
2019-02-14  0:21 ` Jere
2019-02-14 18:04 ` G.B.
2019-02-22  8:42 ` Daniel

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