Приватные типы (private types)
Рассмотрим пример пакета который управляет счетами в бухгалтерской книге.
При этом, нам необходимо осуществлять полный контроль над всеми манипуляциями которые выполняются с объектами, и мы обеспечиваем пользователям пакета только следующие возможности:
- изъятие средств (Withdraw)
- размещение средств (Deposit)
- создание счета (Create)
Никакие другие пакеты не должны иметь представления о деталях реализации внутренней структуры объекта бухгалтерского счета (Account) и, следовательно, иметь к ним доступ.
Для того чтобы выполнить поставленную задачу, мы описываем объект бухгалтерского счета Account как приватный тип:
package Accounts is
type Account is private; -- описание будет представлено позже procedure Withdraw(An_Account : in out Account; Amount : in Money); procedure Deposit( An_Account : in out Account; Amount : in Money); function Create( Initial_Balance : Money) return Account; function Balance( An_Account : in Account) return Integer; private -- эта часть спецификации пакета -- содержит полные описания type Account is record Account_No : Positive; Balance : Integer; end record; end Accounts; |
В результате такого описания, тип Account будет приватным. Следут заметить, что Ада разрешает использовать следующие предопределенные операции над объектами приватного типа вне этого пакета:
- присваивание
- проверка на равенство (не равенство)
- проверки принадлежности ("in", "not in")
Кроме предопределенных операций, над объектами приватного типа, вне этого пакета, разрешается использовать операции, которые объявлены как подпрограммы в спецификации пакета (обычные процедуры и функции, а также функции реализующие действия знаков операций).
Все детали реализации внутреннего представления приватного типа доступны в теле пакета, и любая подпрограмма в теле пакета имеет к ним доступ и может модифицировать приватный тип как обычный тип.
Таким образом, приватность типа сохраняется только вне пакета.
В данном примере необходимо обратить внимание на то, что спецификация пакета разделена на две части.
Все что находится до зарезервированного слова private - это общедоступная часть описаний, которая будет "видна" всем пользователям пакета. Все что находится после зарезервированного слова private - это приватная часть описаний, которая будет "видна" только внутри пакета (и в его дочерних модулях; см. "Дочерние модули").
Может показаться противоречивым размещение приватных описаний в спецификации пакета.
Действительно, мы пытаемся скрыть детали реализации приватного объекта, и размещаем их в спецификации пакета, которая доступна.
Однако, это необходимо для программ, которые размещают экземпляры объектов приватного типа поскольку компилятор, благодаря такой информации, знает сколько необходимо зарезервировать места для размещения экземпляра объекта приватного типа.
Хотя читатель спецификации пакета видит как устроено реальное внутреннее представление реализации приватного типа, это не обеспечивает его возможностью явным и допустимым способом использовать эту информацию.
При этом, примечательным является то, что экземпляры объектов приватного типа могут быть созданы вне пакета.
Например:
with Accounts; use Accounts; procedure Demo_Accounts is Home_Account : Account; Mortgage : Account; This_Account : Account; begin Mortgage := Accounts.Create(Initial_Balance => 500.00); Withdraw(Home_Account, 50); . . . This_Account := Mortgage; -- присваивание приватного типа - разрешено -- сравнение приватных типов if This_Account = Home_Account then . . . end Demo_Accounts; |