Подчеркнем, что в теле определяющего пакета объекты приватных типов ничем не отличаются от любых других - их строение известно, выборка и индексация разрешены!
4.3.3. Строго регламентированный доступ. Ограниченные приватные типы
В общем случае к объектам приватных типов применимы также операции присваивания и сравнения на равенство и неравенство (полных объектов, как в процедуре две_сети!). Хотя это и удобно (такие операции часто нужны и неразумно заставлять программистов определять их для каждого приватного типа), все-таки концепция строго регламентированного доступа в таких типах не выдержана до конца. В Аде она точно воплощена лишь в так называемых ОГРАНИЧЕННЫХ приватных типах. К объектам таких типов неприменимы никакие предопределенные операции, в том числе присваивания и сравнения - все нужно явно определять (в определяющем пакете). Объявления ограниченных приватных типов выделяются ключевыми словами limited private, например:
type ключ is limited private;
Применение к объектам типа "ключ" операций присваивания или сравнения вызовет сообщение об ошибке, если только в определяющем пакете для этого типа не определены свои собственные операции, обозначаемые через ":=", "=" или "/=".
Так как ограниченные приватные типы точно воплощают идею строго регламентированного доступа, интересно понять, в каких же задачах столь строгие ограничения на присваивания и сравнения могут быть существенными.
Присваивания. Мы уже упоминали, что бывают ЯП вовсе без присваивания. Таковы чистый Лисп, Базисный Рефал, функциональные и реляционные языки. Подробнее поговорим о них позже. Чтобы соответствовать роли базового языка, Ада должна предоставлять средства развития, позволяющие моделировать и такие ЯП, причем моделировать в точности, с гарантией защиты создаваемых абстракций. Так что ограниченные приватные типы вместе со средством их определения (пакетом) - важнейшее средство развития в современном базовом ЯП.
Упражнение (повышенной сложности). Создайте определяющий пакет для каждой из рассмотренных далее моделей ЯП.
Замечание (о наблюдении Дейкстры). Подтверждением принципа цельности (согласованности данных, операций, связывания) служит наблюдение Дейкстры, что присваивание нужно лишь в тех языках, где есть повторения (циклы). Именно в циклах появляются переменные, которым нужно присваивать значения (постоянные относительно очередного исполнения тела цикла).
Когда циклов нет и потенциальная бесконечность обслуживается рекурсией (в Лиспе, Рефале, и т. п.), достаточна ИНИЦИАЛИЗАЦИЯ (частный случай присваивания - присваивание начальных значений). Так что наличие циклов должно быть согласовано не только с другими операциями (присваиванием), но и с данными (появляются переменные), а также со связыванием (областью действия каждой переменной в таких ЯП в идеале должен быть некоторый цикл).
Вопрос. Что можно сказать в этих условиях об исходных данных и результатах?
Рассмотрим пример. Допустим, что нужно моделировать выпуск изделий с уникальными номерами (вспомним заводские номера двигателей, автомобилей, самолетов и т. п.). Естественно считать, что объект приватного типа "изделие" - результат базовой для этого типа функции "создать", генерирующей очередное "изделие". Если позволить присваивать объекты этого типа переменным, то станет возможным их дублировать и уникальность будет нарушена. Поэтому тип "изделие" должен быть ограниченным приватным.
Сравнения. Во-первых, операции сравнения для объектов некоторых типов могут попросту не иметь смысла, т. е. объекты могут быть несравнимыми. Из соображений надежности попытку их сравнения следует квалифицировать как ошибку (т. е. сравнение должно быть запрещено). Так, при первоначальном знакомстве с Адой упоминались задачные типы, объекты которых - параллельно исполняемые задачи. Сравнение таких объектов на равенство (при отсутствии присваивания) бессмысленно просто потому, что любой из них уникален по определению. Да и содержательно трудно приписать какой-либо естественный смысл сравнению на равенство (а не, например, на подобие) двух независимо исполняемых задач. Ведь они в постоянном изменении, причем асинхронном, а всякое реальное сравнение занимает время.
Поэтому в Аде задачные типы - ограниченные приватные по определению и, следовательно, всякая попытка сравнить задачи на равенство квалифицируется как ошибка. Кстати, любые составные типы с компонентами ограниченного типа считаются ограниченными.
Во-вторых, нежелание допускать сравнение на равенство может быть связано с защитой от нежелательного доступа, с обеспечением секретности. Так, и пользователи, и файлы в файловой системе могут быть снабжены атрибутами типа "ключ". Однако неразумно разрешать пользователю сравнивать ключи, чтобы решать, пользоваться файлом или нет. Право сравнивать ключи и разрешать доступ должно быть только у самой файловой системы. Поэтому для пользователя тип "ключ" должен быть ограниченным - он может его передать другому, но не может "подделать" или "подобрать".
4.3.4. Инкапсуляция
Определение приватных типов данных - один из примеров инкапсуляции - заключения в "защитную оболочку", предохраняющую от разрушения. Мы видели, как недоступность (защита) строения объектов приватных типов от произвольного доступа со стороны пользователя гарантирует их целостность в некотором содержательном смысле. Понятие инкапсуляции по общности занимает промежуточное положение между концепцией регламентированного доступа и ее конкретной реализацией приватными типами данных.
Приватные типы Ады с точки зрения пользователя - это инкапсулированные (защищенные) типы данных. Однако с точки зрения реализатора тела определяющего пакета - это обычные незащищенные типы. В общем случае инкапсулировать можно не только типы, но и отдельные объекты или системы объектов (таковы объекты, объявленные в теле пакета).
Итак, задача о моделировании сетей помогла проявить технологическую потребность в инкапсуляции и дала повод поработать с конструктами, удовлетворяющими эту потребность, - с объявлениями приватного типа и пакетами.
4.4. Характеристики, связанные с типом. Класс значений, базовый набор операций
Продолжим анализ общей концепции типа данных. До сих пор мы концентрировали внимание только на способе привязки характеристик к объектам данных. Сутью характеристик мы при этом не интересовались. Перед нами очередной пример разумной абстракции. Абстракция от сути характеристик привела к концепции уникальности типа. Концепция уникальности - к простоте прогнозирования-контроля. А простота прогнозирования-контроля позволяет по-новому взглянуть на саму концепцию типа.
Действительно, в ранних ЯП под характеристиками данных обычно понимались характеристики их значений (уже упоминавшиеся разрядность, точность, вид выделяемой памяти и т. п.). Конечно, неявно всегда подразумевалось, что к значениям с одними характеристиками применимы одни операции, а к значениям с другими характеристиками - другие. И раньше чувствовалось, что класс применимых операций - существенная содержательная характеристика класса данных (ведь это естественно следует из понятия данного как разумной абстракции от конкретной операции).
Но идею явного связывания класса данных с классом применимых операций трудно воплотить в рамках структурной эквивалентности типов. Ведь для определения класса данных, к которым применима операция, придется (как, например, в Алголе-68) производить нетривиальные расчеты совокупности данных, структурно эквивалентных параметрам операции.
Именная эквивалентность в концепции уникальности упростила связывание с типом любых характеристик. Легко узнать и классы данных, связанных с любой операцией, - имена типов явно указаны в спецификациях ее параметров.
Может показаться, что нетрудно проделать и обратное - указать для каждого типа все применимые операции. Но представим себе, что пакет управление_сетями предоставлен в распоряжение большого коллектива пользователей. Каждый из них волен написать сегменты, использующие этот пакет, и в этих сегментах ввести свои операции над объектами типа "сети". Например, один ввел процедуру выделения связных подсетей, другой - процедуру подсчета хроматического числа сети, третий - вычисления минимального маршрута между двумя узлами. Следует ли считать характеристикой типа "сети" набор из всех этих операций? И каков содержательный смысл в такой характеристике? Ведь в разных контекстах доступны разные элементы этого набора.
Лучше считать характеристикой типа относительно постоянное его свойство, связанное с ним в любых контекстах. Таковы КЛАСС ЗНАЧЕНИЙ объектов этого типа и БАЗОВЫЙ НАБОР ОПЕРАЦИЙ, применимых к этим объектам. В Аде эти две характеристики связываются с типом соответственно ОБЪЯВЛЕНИЕМ ТИПА и ОПРЕДЕЛЯЮЩИМ ПАКЕТОМ.
4.5. Воплощение концепции уникальности типа. Определение и использование типа в Аде (начало)
Концепция типа воплощена в Аде в основном четырьмя конструктами: объявлением типа, пакетом, объявлением подтипа и объявлением объекта. В совокупности они и позволяют считать, что тип в Аде обладает, кроме имени, еще двумя важнейшими характеристиками - классом значений и набором применимых операций. С каждым из названных четырех конструктов мы уже встречались. Поговорим подробнее об их строении, смысле и взаимодействии.
4.5.1. Объявление типа. Конструктор типа. Определяющий пакет
Объявление типа вводит имя нового типа и связывает это имя с конструктором типа. Последний служит для создания нового типа из уже известных и располагается в объявлениях типов после ключевого слова is.
Создать (объявить) новый тип в Аде - значит определить класс допустимых значений объектов этого типа и набор базовых операций, связанных с создаваемым типом.
В Аде предопределены некоторые типы данных (обслуживающие наиболее общие потребности проблемной области - универсальный_целый, универсальный_вещественный и другие), а также класс допустимых значений перечисляемых типов. Кроме того, предопределены операции, применимые к объектам целых категорий типов.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |


