From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_00,FROM_WORDY autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,772ae8afc5db35f2 X-Google-Attributes: gid103376,public From: "Nick Roberts" Subject: Re: Can't export object of private type Date: 1999/03/04 Message-ID: <7bmgfb$2d3$1@plug.news.pipex.net> X-Deja-AN: 451223295 References: <7bk6gh$6d9$2@plug.news.pipex.net> X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3 Organization: UUNET WorldCom server (post doesn't reflect views of UUNET WorldCom) Newsgroups: comp.lang.ada Date: 1999-03-04T00:00:00+00:00 List-Id: Don Harrison wrote ... |Nick Roberts wrote: | |:Also, you need to remove the function Solo_T from package T (it does nothing | |It exports a reference to the singleton. It's definitiely unnecessary, and doesn't export anything (that needs to be exported). It is unnecessary. |: .. and won't compile), | |GNAT didn't have any trouble. I have to agree with this -- I've tried it myself. I'm still trying to work out why. The whole thing also works perfectly well if you delete this function declaration too (try it!). |:and move the declaration of Self from the private part |:of package T.Child (where it doesn't need to be, and will cause an |:unnecessary dependency) to the package's body. | |An unnecessary dependency on what? The idea is to move everything not to do with the 'public' face of your singletons out of package specs and into the bodies. This way, if you nned to change anything about the implementation of these objects, it will only cause recompilation of the package bodies: if you have to change anything in the specs, this will (potentially) cause (the necessity of) recompilation of the specs, the bodies AND all the clients which use the specs. You generally want to avoid this. |:The 'access' parameters in |:the subprograms need only be 'in out' parameters; this is (pointedly!) a |:case where access parameters serve no useful purpose.. | |The access-parameters serve two useful purposes: | | - An access entity of any access type to T_Type'Class can be used | as an actual parameter. It can still be used with 'in out' parameters, you just have to dereference them explicitly (by adding '.all'). However, the 'access' form is therefore slightly more convenient (so I have used these in my example below). There is otherwise no difference in this example. | - That entity can't be corrupted because access-parameters are | in-mode. Wrong. The access value itself can't be changed, but the entity it references can. |: (because the objects |:are always going to be declared at library level). | |: type T_Array_Type is array (T_Index_Type) of Access_Class_T_Type; |: |: T_Array: T_Array_Type := ( |: 1 => T.Child.Solo_T.all'Access, -- 1) |: 2 => T.OTher_Child.Solo_T.all'Access); -- 1) | |This is client - not library - code. I think you misunderstand. The singleton objects are always going to be declared at library level (we can be sure of this precisely because we have prevented clients from creating these objects). Objects which hold access values -- so long as they are of the access types we have provided (also declared at at library level) -- don't matter. |Otherwise: perfect! | |Thanks! :) You're most welcome, but I think you're example may not actually have been quite perfect :-( However, I have provided a template example below which is :-) I hope ;-) This shows no less than two levels of derivation, and may seem a little 'overkill'. However, it is in the nature of small examples to do so: the structure provided here will provide insulation from change, something of great value for real-life (big!) systems. I'm still learning about this stuff myself, so I'm grateful to Don et al for making me investigate these things. (Corollary: nothing I say should be taken as Gospel by anyone :-) Incidentally, that I've cast my examples in terms of planets is purely arbitrary. |Don (Harrison). donh at syd.csa.com.au ------------------------------------- Nick Roberts ------------------------------------- package Planetary is type Solar_Planet(<>) is abstract tagged limited private; procedure Put_Name (Planet: access Solar_Planet) is abstract; type Planet_Access is access all Solar_Planet'Class; --function The_Planet return Planet_Access is abstract; private type Solar_Planet is abstract tagged limited record Base: String(1..11) := "The Planet "; end record; end; package Planetary.Mercury is type Planet_Mercury is abstract new Solar_Planet with private; type Mercury_Access is access all Planet_Mercury'Class; function The_Planet return Mercury_Access; private type Planet_Mercury is abstract new Solar_Planet with record Extra: String(1..7) := "Mercury"; end record; end; with Ada.Text_IO; use Ada.Text_IO; with Ada.Exceptions; use Ada.Exceptions; package body Planetary.Mercury is package Inner is type Mercury_Secrets is new Planet_Mercury with record Special: String(1..8) := " Innards"; end record; procedure Put_Name (Planet: access Mercury_Secrets); end; package body Inner is procedure Put_Name (Planet: access Mercury_Secrets) is begin Put_Line (Planet.Base & Planet.Extra & Planet.Special); exception when E: others => Put_Line("Exception raised in Mercury.Put_Name"); Put(Exception_Information(E)); New_Line; raise; end; end Inner; Internal: aliased Inner.Mercury_Secrets; function The_Planet return Mercury_Access is begin return Internal'Access; exception when E: others => Put_Line("Exception raised in Mercury.The_Planet"); Put(Exception_Information(E)); New_Line; raise; end; end; with Ada.Text_IO; use Ada.Text_IO; with Ada.Exceptions; use Ada.Exceptions; with Ada.Tags; use Ada.Tags; with Planetary.Mercury; use Planetary; procedure Main is P1: Planet_Access := Planet_Access(Mercury.The_Planet); begin Put_Line("P1 tag = " & Expanded_Name(P1.all'Tag)); Put_Name(P1); -- dispatching exception when E: others => Put_Line("Exception raised in Main"); Put(Exception_Information(E)); New_Line; raise; end;