Принудительная инициализация
В объектно-ориентированных языках программирования, которые используют классы (например язык C++), можно принудительно навязать автоматическую инициализацию для всех объектов класса, снабдив класс конструктором, который гарантированно вызывается при создании объекта.
Чтобы добиться подобного эффекта в Аде, необходимо при описании объекта указать присваивание начального значения, которое осуществляется в результате вызова функции.
Следует заметить, что в данном случае мы не рассматриваем средства, которые предоставляют контролируемые типы Ады.
Рассмотрим следующий пример:
package Stacks is
type Stack is tagged private; function Init return Stack; -- другие операции . . . private type List is array(1..10) of Integer; type Stack is record Values : List; Top : Integer range 0..10; end record; end Stacks; with Stacks; use Stacks; procedure Main is A : Stack := Init; B : Stack; begin null; end Main; |
В этом примере объект A будет надежно инициализирован для представления пустого стека.
Причем, для этого можно использовать только функции предусмотренные пакетом Stacks.
Выполнить инициализацию такого объекта каким-либо другим способом - нельзя, поскольку его тип - приватный.
Однако, не трудно заметить, что объект B - не инициализирован.
Таким образом видно, что Ада не предъявляет никаких требований по принудительной инициализации объектов.
Чтобы в подобных случаях возложить контроль за инициализацией объектов на компилятор необходимо использовать дискриминанты.
Существует возможность указать наличие дискриминанта в неполном описании типа при фактическом отсутствии дискриминанта в полном описании типа.
Поскольку Ада предпочитает ограниченные (constrained) объекты (то есть те объекты, размер которых известен), то применение комбинации из дискриминанта и приватного типа послужит причиной того, что компилятор будет требовать от программиста явной инициализации всех объектов такого типа.
package Stacks is
type Stack(<>) is private; -- указание того, что Stack может иметь дискриминант... function Init return Stack; -- другие операции . . . private type List is array(1..10) of Integer; -- ...даже если вы не стремитесь иметь здесь дискриминант type Stack is record Values : List; Top : Integer range 0..10; end record; end Stacks; with Stacks; use Stacks; procedure Main is A : Stack := Init; B : Stack; -- теперь это недопустимо! -- вы должны вызвать функцию для инициализации B begin null; end Main; |
Подобный подход может показаться несколько интуитивным, однако за счет явности описаний инициализации он повышает общую читабельность исходного текста.