Reputation: 331
I'm trying to hide some aspects of a library to the users and reading the RM for type conversions, I can't understand why the following code fails.
A user will instantiate root.child.concrete.concrete_t and then will call to root.p_userInterface passing that instance, but a compilation error is being thrown on root.adb: invalid tagged conversion, not compatible with type "child_t'class" defined at root-child.ads:4
root.ads:
limited with root.child;
package root is
procedure p_userInterface (obj : in out root.child.child_t'Class);
private
type root_t is abstract tagged null record;
procedure p_primitive (this : in out root_t) is abstract;
end root;
root.adb:
with root.child;
package body root is
procedure p_userInterface (obj : in out root.child.child_t'Class) is
begin
-- error: invalid tagged conversion, not compatible with type "child_t'class" defined at root-child.ads:4
root_t'Class(obj).p_primitive;
end p_userInterface;
end root;
root-child.ads:
package root.child is
type child_t is abstract tagged private;
function f_getComponent(this : in child_t) return Integer;
private
type child_t is abstract new root_t with
record
component : Integer;
end record;
overriding
procedure p_primitive (this : in out child_t) is abstract;
end root.child;
root-child.adb:
package body root.child is
function f_getComponent(this : in child_t) return Integer is
begin
return this.component;
end f_getComponent;
end root.child;
root-child-concrete.ads:
package root.child.concrete is
type concrete_t is new child_t with private;
procedure p_setAnotherComponent (this : in out concrete_t;
c : Boolean);
function f_getAnotherComponent (this : concrete_t) return Boolean;
private
type concrete_t is new child_t with
record
anotherComponent : Boolean;
end record;
overriding
procedure p_primitive (this : in out concrete_t);
end root.child.concrete;
root-child-concrete.adb:
package body root.child.concrete is
procedure p_primitive (this : in out concrete_t) is
begin
-- for example
this.anotherComponent := True;
end p_primitive;
procedure p_setAnotherComponent (this : in out concrete_t;
c : Boolean) is
begin
this.anotherComponent := c;
end p_setAnotherComponent;
function f_getAnotherComponent (this : concrete_t) return Boolean is
begin
return this.anotherComponent;
end f_getAnotherComponent;
end root.child.concrete;
Why? I understand that the implementation of root is not able to see the private part of its root.child child package, thus is not able to see that type child_t is extending root_t privately. Am I right?
Can I achieve something like this differently? I would like to hide p_primitive to the users because is to perform internal things, but I would like to dispatch it internally if it's possible.
Upvotes: 1
Views: 120
Reputation: 331
I think I have finally achieved it. Here is the solution that works for me, only on changed units, commenting out the old parts, as I can't use html strike tag to cross out code:
root.ads:
--limited with root.child;
package root is
type root_t is abstract tagged null record;
procedure p_userInterface (obj : in out root_t'Class); --root.child.child_t'Class);
private
--type root_t is abstract tagged null record;
--procedure p_primitive (this : in out root_t) is abstract;
type hiddenRoot_t is abstract new root_t with null record;
procedure p_primitive (this : in out hiddenRoot_t) is abstract;
end root;
root.adb:
--with root.child; It was not needed before neither
package body root is
procedure p_userInterface (obj : in out root_t'Class) is --root.child.child_t'Class) is
begin
--root_t'Class(obj).p_primitive; -- invalid tagged conversion, not compatible with type "child_t'class"
hiddenRoot_t'Class(obj).p_primitive;
end p_userInterface;
end root;
root-child.ads:
package root.child is
--type child_t is abstract tagged private;
type child_t is abstract new root_t with private;
function f_getComponent(this : in child_t) return Integer;
private
--type child_t is abstract new root_t with
type child_t is abstract new hiddenRoot_t with
record
component : Integer;
end record;
overriding
procedure p_primitive (this : in out child_t) is abstract;
end root.child;
This way I'm able to dispatch privately to the implementation of p_primitive of a concrete_t type, and on a main I can ensure that an instance of concrete_t has no visibility of p_primitive. Any further comment to this solution will be appreciated, I do not know if I'm missing something important, but seems to work. I have no idea if it is the correct solution.
Upvotes: 1