Go to the first, previous, next, last section, table of contents.


7.3.1 Private Operations

  1. For a type declared in the visible part of a package or generic package, certain operations on the type do not become visible until later in the package -- either in the private part or the body. Such private operations are available only inside the declarative region of the package or generic package.

    Static Semantics

  2. The predefined operators that exist for a given type are determined by the classes to which the type belongs. For example, an integer type has a predefined "+" operator. In most cases, the predefined operators of a type are declared immediately after the definition of the type; the exceptions are explained below. Inherited subprograms are also implicitly declared immediately after the definition of the type, except as stated below.
  3. For a composite type, the characteristics, See section 7.3 Private Types and Private Extensions of the type are determined in part by the characteristics of its component types. At the place where the composite type is declared, the only characteristics of component types used are those characteristics visible at that place. If later within the immediate scope of the composite type additional characteristics become visible for a component type, then any corresponding characteristics become visible for the composite type. Any additional predefined operators are implicitly declared at that place.
  4. The corresponding rule applies to a type defined by a derived_type_definition, if there is a place within its immediate scope where additional characteristics of its parent type become visible.
  5. For example, an array type whose component type is limited private becomes nonlimited if the full view of the component type is nonlimited and visible at some later place within the immediate scope of the array type. In such a case, the predefined "=" operator is implicitly declared at that place, and assignment is allowed after that place.
  6. Inherited primitive subprograms follow a different rule. For a derived_type_definition, each inherited primitive subprogram is implicitly declared at the earliest place, if any, within the immediate scope of the type_declaration, but after the type_declaration, where the corresponding declaration from the parent is visible. If there is no such place, then the inherited subprogram is not declared at all. An inherited subprogram that is not declared at all cannot be named in a call and cannot be overridden, but for a tagged type, it is possible to dispatch to it.
  7. For a private_extension_declaration, each inherited subprogram is declared immediately after the private_extension_declaration if the corresponding declaration from the ancestor is visible at that place. Otherwise, the inherited subprogram is not declared for the private extension, though it might be for the full type.
  8. The Class attribute is defined for tagged subtypes in 3.9. In addition, for every subtype S of an untagged private type whose full view is tagged, the following attribute is defined:
  9. S'Class
    Denotes the class-wide subtype corresponding to the full view
    of S. This attribute is allowed only from the beginning of
    the private part in which the full view is declared, until
    the declaration of the full view. After the full view, the
    Class attribute of the full view can be used.
    

    NOTES

  10. (8) Because a partial view and a full view are two different views of one and the same type, outside of the defining package the characteristics of the type are those defined by the visible part. Within these outside program units the type is just a private type or private extension, and any language rule that applies only to another class of types does not apply. The fact that the full declaration might implement a private type with a type of a particular class (for example, as an array type) is relevant only within the declarative region of the package itself including any child units.
  11. The consequences of this actual implementation are, however, valid everywhere. For example: any default initialization of components takes place; the attribute Size provides the size of the full view; finalization is still done for controlled components of the full view; task dependence rules still apply to components that are task objects.
  12. (9) Partial views provide assignment (unless the view is limited), membership tests, selected components for the selection of discriminants and inherited components, qualification, and explicit conversion.
  13. (10) For a subtype S of a partial view, S'Size is defined, See section 13.3 Representation Attributes. For an object A of a partial view, the attributes A'Size and A'Address are defined, See section 13.3 Representation Attributes. The Position, First_Bit, and Last_Bit attributes are also defined for discriminants and inherited components.

    Examples

  14. Example of a type with private operations:
  15. package Key_Manager is
       type Key is private;
       Null_Key : constant Key;
       -- a deferred constant declaration, See section 7.4 Deferred Constants
       procedure Get_Key(K : out Key);
       function "<" (X, Y : Key) return Boolean;
    private
       type Key is new Natural;
       Null_Key : constant Key := Key'First;
    end Key_Manager;
    
  16. package body Key_Manager is
       Last_Key : Key := Null_Key;
       procedure Get_Key(K : out Key) is
       begin
          Last_Key := Last_Key + 1;
          K := Last_Key;
       end Get_Key;
    
  17.    function "<" (X, Y : Key) return Boolean is
       begin
          return Natural(X) < Natural(Y);
       end "<";
    end Key_Manager;
    

    NOTES

  18. (11) Notes on the example: Outside of the package Key_Manager, the operations available for objects of type Key include assignment, the comparison for equality or inequality, the procedure Get_Key and the operator "<"; they do not include other relational operators such as ">=", or arithmetic operators.
  19. The explicitly declared operator "<" hides the predefined operator "<" implicitly declared by the full_type_declaration. Within the body of the function, an explicit conversion of X and Y to the subtype Natural is necessary to invoke the "<" operator of the parent type. Alternatively, the result of the function could be written as not (X >= Y), since the operator ">=" is not redefined.
  20. The value of the variable Last_Key, declared in the package body, remains unchanged between calls of the procedure Get_Key. (See also the NOTES of See section 7.2 Package Bodies.)


Go to the first, previous, next, last section, table of contents.