* 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