Mombu the Programming Forum sponsored links

Go Back   Mombu the Programming Forum > Programming > Indirect visibility of private part in child packages
User Name
Password
REGISTER NOW! Mark Forums Read

sponsored links


Reply
 
1 1st July 03:38
hibou57_(yannick_duchêne)
External User
 
Posts: 1
Default Indirect visibility of private part in child packages



Hi all,

I've meet a tortuous question with a set of packages I'm converting
from Pascal (as I use Ada now, I'm taking the opportunity to re-create
a nicer design).

The question I'm facing deals with visibility of private part in child
package. More precisely, an indirect visibility of a private part. An
exemple will better show the case:

This can be reduced to three package (specs and bodies)

The root package:


package P1 is
type T1_Type is tagged private;
-- Some primitives on T1_Type are specified here ...
private
type T1_Type is tagged record
Low_Level_Data : Some_Type;
end record; -- T1_Type
end P1;
<<<<< --------------------------------------------------

The first child package (with this one, every thing's Ok):

package P1.P2 is
type T2_Type is new T1_Type with private;
-- Some primitives on T2_Type are specified here ...
procedure A_Primitive (Item : out T2_Type);
private
type T2_Type is new T1_Type with null record;
end P1.P2;

package body P1.P2 is
procedure A_Primitive (Item : out T2_Type) is
begin
Item.Low_Level_Data := ...;
-- It works, beceause P1.P2 is a child
-- package with a view on P1's private part
end A_Primitive;
end P1.P2;
<<<<< --------------------------------------------------

The second child package (the one which turns into a subtile doubt):

with P1.P2;
package P1.P3 is
type T3_Type is new P1.P2.T2_Type with private;
-- Some primitives on T2_Type are specified here ...
procedure A_Primitive (Item : out T3_Type);
private
type T3_Type is new P1.P2.T2_Type with null record;
end P1.P3;

package body P1.P3 is
procedure A_Primitive (Item : out T3_Type) is
begin
Item.Low_Level_Data := ...;
-- It fails : the compiler complains there is no
-- selector "Low_Level_Data" defined for T3_Type
end A_Primitive;
end P1.P3;
<<<<< --------------------------------------------------

As said in the last comment, it seems P1.P3 cannot see the
T1_Type.Low_Level_Data member. But as P3 is a child package of P1, it
has a view on P1's private part, and there is indeed no trouble about
it with P2. P3 know P2.T2_Type is derived from P1.T1_Type, and P3 has
a view on T1_Type privates. But it seems the compiler does not care
about it.

There may be interpretation matter here : does the private
specification, means "disallow access to private part" or does it
means "do not provide an access to the private part". If it means
"disallow access to private part", then it ill explain why P3 cannot
access T1_Type.Low_Level_Data member. But if it means "do no provide
an access to private" part, then P3 should still be able to access
T1.Low_Level_Data, beceause it has an access to this as a child
package of P1.

What does long experienced lawyers think about it ?

I've try to look in section 8 of the "RM 2005", but either the answer
was not there or else, I missed it.

Note #1: I hope my exemple is clear enought. If it is not, please,
tell me, so that I can attempt to reword it.

Note #2: I do not want to make P3 a child package of P2, beceause it
does not need to access any internals of T2_Type. I want to have some
types, extending each others, and doing so only relying on either
public interface or on the sole common private part defined in P1.
  Reply With Quote


  sponsored links


2 1st July 03:38
ludovic brenta
External User
 
Posts: 1
Default Indirect visibility of private part in child packages



Maybe you can solve your problem like this:

package body P1.P3 is
procedure A_Primitive (Item : out T3_Type) is
begin
T1_Type (Item).Low_Level_Data := ...;
end A_Primitive;
end P1.P3;

I am undecided whether the compiler is correct or wrong about the
visibility of Low_Level_Data. On the one hand, P1.P3 cannot see the
full declaration of T2_Type; on the other hand, it can see that
T2_Type publicly inherits from T1_Type and can also see the full
declaration of T1_Type.

It seems that the public (partial) view of T2_Type hides the full
declaration of T1_Type. So, I think my solution would work by removing
T2_Type out of the way.

Another solution, which enforces encapsulation better, would be:

package P1 is
type T1_Type is tagged private;
private
type Some_Type is ...;
type T1_Type is tagged record
Low_Level_Data : Some_Type;
end record;
procedure Set (Item : out T1_Type; Data : in Some_Type);
end P1;

package body P1.P3 is
procedure A_Primitive (Item : out T3_Type) is
begin
Set (Item, Data => ...); -- OK, calls inherited primitive
operation
end A_Primitive;
end P1.P3;

HTH

--
Ludovic Brenta.
  Reply With Quote


  sponsored links


3 1st July 03:38
hibou57_(yannick_duchêne)
External User
 
Posts: 1
Default Indirect visibility of private part in child packages


Bonjour Ludovic, and thanks for your reply

I've just tried it, and it does not work better. The compiler
complains there are not selector Low_Level_Data for T1_Type.

This is exactly the same think in my mind. Perhaps the semantic is ambigous here.


T2_Type is required The purpose is to have T2_Type and T3_Type, and
may be later some others, beside of each other.


I will try it soon and tell about the result. But at first sight, I
think that the compiler gonna complain that Set is a primitive of
T1_Type and thus that it must be defined in the public part. Further
more, I think Set would habe to be redefined for each T2_Type, T3_Type
and etc.

Will try and tell later

Have a nice day
  Reply With Quote
4 1st July 03:38
robert a duff
External User
 
Posts: 1
Default Indirect visibility of private part in child packages


"Hibou57 (Yannick Duchêne)" <yannick_duchene@yahoo.fr> writes:


Are you sure? Converting to T1_Type should work. P3 can see that
T1_Type has a Low_Level_Data component.

The reason your original example didn't work is that the components of
T2_Type are "nailed down" at the point where it's declared,
and P3 can't see that. It can, however, see that it's derived
from T1_Type, so converting should work.

You could make Set class-wide.

- Bob
  Reply With Quote
5 1st July 03:38
hibou57_(yannick_duchêne)
External User
 
Posts: 1
Default Indirect visibility of private part in child packages


I sware, it is rejected. I agree this is strange.

A GNAT bug ? If it is, perhaps this is the answer to the other
question as well (the question about the visibility).
  Reply With Quote
6 1st July 03:39
adam beneschan
External User
 
Posts: 1
Default Indirect visibility of private part in child packages


Here's why it doesn't work:

The "operation" of providing a selector Low_Level_Data for T1_Type is
made visible in the private part of P1.

When T2_Type is declared as derived from T1_Type, the operation of
providing the selector Low_Level_Data is inherited from T1_Type, but
it only becomes visible where the original operation becomes visible.
Since the original operation is visible in the private part of P1, the
inherited operation becomes visible in the private part of P1.P2,
which is the first place that the private part of P1 is visible.
(It's not relevant that T2_Type is a private extension; I believe it
would work the same if T2_Type were fully declared in the visible
part.)

When T3_Type is declared as derived as T2_Type, the operation of
providing the selector Low_Level_Data is inherited from T2_Type, but
it only becomes visible where the original operation (on T2_Type!!)
becomes visible, which is... nowhere, because there isn't anywhere in
P1.P3 that is able to access P1.P2's private part (and according to
the above paragraph, that's where the operation on T2_Type is made
visible---in P1.P2's private part). That's why Low_Level_Data isn't
available for T3_Type.

So the compiler is correct to reject your original program. However,
I think Ludovic's fix (using a type conversion, actually a view
conversion) should work, and it's a compiler bug if that is rejected.

One could argue that this rule is anomalous, and that if a type is
visibly derived from a grandparent (or great-grandparent, etc.) type
in a situation like this, then operations that are indirectly
inherited from the grandparent (etc.) type should be visible if
they're visible for the grandparent, even if the inheritance comes
indirectly through a non-visible part of some other package. There
could be a privacy problem if the operation could be overridden in the
non-visible part, but that isn't possible here---there's nothing P1.P2
can do to change the meaning of the Low_Level_Data selector. This
issue is related to AI05-125, but although a couple of us think
there's a flaw in the language, others believe that it can't be fixed
without making things even more confusing. In any event, it's not all
that important here since the view conversion is an adequate
workaround, assuming your compiler isn't broken.

I think 7.3.1 and particularly 7.3.1(4) is the important rule here,
although I have to admit that that section uses a lot of slightly
fuzzy generalities that I've had problems interpreting occasionally.

-- Adam
  Reply With Quote
7 1st July 03:39
hibou57_(yannick_duchêne)
External User
 
Posts: 1
Default Indirect visibility of private part in child packages


I've done an error in my prior : T1_Type(Item).Low_Level_Data finally
works fine.

By the way, thanks for this clean explanation (and I gonna have a
further look at 7.3x)
  Reply With Quote
Reply


Thread Tools
Display Modes




Copyright © 2006 SmartyDevil.com - Dies Mies Jeschet Boenedoesef Douvema Enitemaus -
666