The Destructor
aspect can be applied to any record type, tagged or not.
It must denote a primitive of the type that is a procedure with one parameter
of the type and of mode in out
:
type T is record ... end record with Destructor => Foo; procedure Foo (X : in out T);
This is equivalent to the following code that uses Finalizable
:
type T is record ... end record with Finalizable => (Finalize => Foo); procedure Foo (X : in out T);
Unlike Finalizable
, however, Destructor
can be specified on a derived
type. And when it is, the effect of the aspect combines with the destructors of
the parent type. Take, for example:
type T1 is record ... end record with Destructor => Foo; procedure Foo (X : in out T1); type T2 is new T1 with Destructor => Bar; procedure Bar (X : in out T2);
Here, when an object of type T2
is finalized, a call to Bar
will be performed and it will be followed by a call to Foo
.
The Destructor
aspect comes with a legality rule: if a primitive procedure
of a type is denoted by a Destructor
aspect specification, it is illegal to
override this procedure in a derived type. For example, the following is illegal:
type T1 is record ... end record with Destructor => Foo; procedure Foo (X : in out T1); type T2 is new T1; overriding procedure Foo (X : in out T2); -- Error here
It is possible to specify Destructor
on the completion of a private type,
but there is one more restriction in that case: the denoted primitive must
be private to the enclosing package. This is necessary due to the previously
mentioned legality rule, to prevent breaking the privacy of the type when
imposing that rule on outside types that derive from the private view of the
type.