Отношение наследования для типов со сложным поведением

ОТНОШЕНИЕ НАСЛЕДОВАНИЯ ДЛЯ ТИПОВ СО СЛОЖНЫМ ПОВЕДЕНИЕМ Н.И. Поликарпова Научный руководитель - кандидат технических наук Д.Г. Шопырин

В работе рассматривается объектно-ориентированный подход к моделированию и спецификации сущностей со сложным поведением; строится определение типа со сложным поведением, предлагается метод формальной спецификации и определение отношения наследования для таких типов.

Введение

В процессе создания программного обеспечения часто возникает необходимость реализации сущностей со сложным поведением. Таким свойством обладают устройства управления, сущности, отвечающие за взаимодействие других сущностей между собой и с пользователем, сущности, реализующие сетевые протоколы, и многие другие.

Можно сказать, что объект обладает сложным поведением, если в ответ на возникновение некоторого события он может совершить одно из нескольких действий. Выбор действия зависит от информации, хранимой внутри и вне данного объекта на текущем шаге вычисления, а также на всех предыдущих шагах. При наивной программной реализации таких сущностей возникают избыточные переменные, называемые флагами, которым не соответствуют никакие элементы предметной области. Единственное предназначение флагов - участвовать в многочисленных, запутанных конструкциях ветвления, реализующих логику поведения. Это решение трудно для понимания, подвержено ошибкам и практически не расширяемо.

Вместо этого предлагается описывать объект со сложным поведением, приписав ему некоторое множество управляющих состояний, в каждом из которых поведение объекта является «простым» и может быть описано непосредственно. Вся логика поведения оказывается сосредоточенной в механизме переходов между состояниями. Связь управляющих состояний с поведением и механизм переходов удобно описывать с помощью конечного автомата с выходами [1]. Поэтому такой подход к описанию сложного поведения часто называют автоматным.

Те или иные модификации диаграмм переходов конечных автоматов применяются для описания сложного поведения в ряде известных методологий спецификации компьютерных систем, таких как UML [2], Statemate [3], SWITCH-технология [4]. Две последних из них не являются объектно-ориентированными. Например, в подходе Statemate в качестве первого шага спецификации концептуальной модели системы предлагается осуществить ее функциональную декомпозицию - представить систему в виде набора взаимосвязанных деятелъностей. После этого поведение всей системы в целом предлагается описать в терминах деятельностей при помощи диаграммы Statechart, которая является компактным описанием конечного автомата.

Язык моделирования UML, напротив, основан на объектно-ориентированных концепциях. В объектно-ориентированной методологии основным видом декомпозиции является объектная - представление системы в виде набора взаимодействующих абстрактных типов данных (АТД). В UML для обозначения этой абстракции используется термин класс, однако автор предпочитает применять этот термин по отношению к реализации абстракций в некотором объектно-ориентированном языке программирования. Несмотря на основополагающую разницу в методологии, UML предполагает использование диаграмм Statechart тем же образом, что и Statemate - для описания поведения всей системы в целом или произвольной ее части.

С точки зрения автора, действительно объектно-ориентированным подходом к описанию сложного поведения было бы выделение из совокупности АТД, описываю-

щей систему, типов, моделирующих сущности со сложным поведением, и применение автоматного подхода для описания поведения каждого из этих типов в отдельности. Таким образом, мы приходим к понятию автоматизированного абстрактного типа данных (ААТД) - типа данных, содержащего конечный автомат, управляющий его поведением.

При спецификации компьютерной системы с использованием автоматизированных типов данных сложное поведение инкапсулируется - пользователь может обращаться с ААТД так же, как с обыкновенным типом. Это позволяет применять для построения системы как целого привычные объектно-ориентированные приемы, такие как порождение подтипов и композиция объектов. Предлагаемый подход способствует большей модульности специфицируемой системы и повторному использованию реализованных типов со сложным поведением.

В дальнейших разделах настоящей работы вводится понятие автоматизированного абстрактного типа данных. Предлагается метод спецификации ААТД, основанный на сочетании существующих языков спецификации типов данных и конечных автоматов, и описывается алгоритм преобразования спецификации ААТД в спецификацию обыкновенного типа данных. Эквивалентность двух спецификаций позволяет легко переносить на ААТД свойства и отношения, характерные для обыкновенных типов данных. Из всех рассматриваемых обычно отношений между типами отношение «.является подтипом» (или отношение наследования) трактуется наиболее неоднозначно, несмотря на то, что оно повсеместно используется на практике. В статье [5] были даны два формальных определения отношения наследования. В настоящей работе рассматривается применение одного из них к автоматизированным типам данных.

Понятие автоматизированного абстрактного типа данных

Прежде всего, уточним, что понимается в настоящей работе под абстрактным типом данных.

Определение 1. Абстрактным типом данных называется пара

t = T, M),

где T - множество значений (или вычислительных состояний), M = {m | m = (i, Args , Ret , f)} - конечное множество методов. Каждый метод включает в себя имя i, набор типов аргументов Args, тип возвращаемого значения Ret и, наконец, исполняющую функцию f : T х {Obj : Args} {T х {Obj : Ret}}* (запись {Obj: Types} означает множество всех объектов, принадлежащих к соответствующим типам или типу).

Рис. 1. Абстрактный тип данных

Абстрактный тип данных схематично изображен на рис. 1. Совокупность отвечающих методу типов Args и Ret определяет его сигнатуру, а исполняющая функция -его семантику. Как следует из определения, исполняющая функция не всегда однозначно определяет новое вычислительное состояние и возвращаемое значение. Для некоторых значений аргументов она может быть не определена, а для других существует

несколько вариантов результата (это оставляет определенную свободу реализации АТД в программе).

Далее будем обозначать метод с именем i через mi, типы его аргументов и возвращаемого значения - через mi.Args и mi .Ret, соответственно. Если необходимо явно указать его принадлежность к множеству методов абстрактного типа t , будем писать t :: mi.

Если абстрактный тип данных является моделью сущности со сложным поведением, исполняющие функции его методов обычно трудны для понимания и спецификации. В терминах данного выше понятия сложного поведения они содержат описания нескольких простых действий, объединенные условными конструкциями. В соответствии с автоматным подходом можно специфицировать простые функции-действия отдельно и приписать их типу управляющий автомат, задача которого - осуществлять диспетчеризацию вызовов функций-действий в зависимости от имени метода (события) и от управляющего состояния. Чтобы различать функции-действия, удобно присвоить им собственные имена. Именованные функции-действия образуют множество методов некоторого нового типа данных, который, по отношению к первичному типу, моделирующему сущность со сложным поведением, будем называть вложенным. Таким образом, модель сущности со сложным поведением представляется в виде совокупности управляющей и вычислительной компонент. Эта конструкция получила название разомкнутого автоматизированного абстрактного типа данных (его отличие от замкнутого ААТД обсуждается ниже).

Определение 2. Разомкнутым автоматизированным абстрактным типом данных будем называть пару (A,t), где A - управляющий автомат, t - вложенный абстрактный тип данных.

Управляющий автомат представляет собой пятерку

A = (S, E, Z, s0, А),

где S - конечное множество управляющих состояний, E - конечное множество входных символов (или событий), Z - конечное множество действий, s0 е S - начальное

(стартовое) состояние, А : S х E  S х Z - управляющая функция.

Управляющую функцию можно разложить на две компоненты Z и 5 , где Z : S х E  Z - функция действий, 5 : S х E  S - функция переходов.

Пусть I - множество имен методов вложенного типа t , тогда Z ^ I.

Рис. 2. Разомкнутый ААТД

Разомкнутый ААТД изображен на рис. 2. Прямыми стрелками на рисунке обозначена передача данных, множество значений которых заведомо конечно, а волнистыми

стрелками - передача элементов потенциально бесконечных множеств. Как следует из рис. 2, управляющий автомат преобразует только события, но не влияет на аргументы методов, и вообще, управляющая функция автомата оперирует исключительно конечными множествами. Это важное свойство позволяет задавать ее значения в явном виде для всех возможных аргументов (с помощью таблицы или диаграммы переходов). Именно поэтому конечные автоматы удобны для описания логики сложного поведения.

Целью автора было определить автоматизированный тип данных как частный случай обыкновенного АТД. Покажем, что разомкнутый ААТД (A,t) действительно

является типом данных (назовем его t'). В качестве множества значений типа t' возьмем декартово произведение T х S множества значений вложенного типа и множества управляющих состояний автомата. Именами для методов нового типа будут служить события ААТД. Каковы будут сигнатуры этих методов? Если "e е E $Argse : "s е S mz.Args = Argse, где z = Z (s, e) , можно определить набор типов аргументов метода me как Argse. То же справедливо и для типа возвращаемого значения. Однако это - слишком сильное требование: в действительности, для правильной работы любого метода автоматизированного типа аргументы me должны только содержать достаточно информации для вызова любого из сопоставляемых ему методов mz, и наоборот, возвращаемое значение любого из методов mz должно быть пригодно для возврата из me.

Пусть построен метод me типа t'. В некотором управляющем состоянии s он сопоставляется методу mz с именем z = Z (s, e) вложенного типа t . Разумно выдвинуть для этих методов следующее правило сигнатур:

• Контравариантностъ аргументов. Количество аргументов me и mz одинаково. Пусть ai набор типов аргументов me, а ßi - соответствующий набор для mz. Тогда

"i aг < ß,. \

• Ковариантностърезулътата. Оба метода me и mz одновременно либо возвращают результат, либо нет. Пусть результат существует. Тогда, если результат me имеет тип g , а результат mz - тип 5 , то 5 < g .

Аналогичное правило сигнатур используется при определении понятия подтипа в работе [5]. Взяв его за основу, можно определить сигнатуру любого метода me типа t' следующим образом:

"k me Argsk = mint :: mz (s ,e)Argsk

m .Ret = max t :: mrt vRet

e seS Z

Если общего подтипа соответствующих типов аргументов (или общего супертипа типов возвращаемых значений) не существует, тип t' не может быть построен и автоматизированный тип (A,t) является некорректным.

Отметим, что при спецификации автоматизированного типа данных правило сигнатур можно использовать как для построения интерфейса ААТД по известному интерфейсу вложенного типа, так и наоборот. Кроме того, если интерфейсы обоих типов и управляющая функция автомата заданы, можно использовать правило сигнатур для проверки их непротиворечивости.

Исполняющие функции методов t' строятся тривиальным образом из исполняющих функций методов t , соответствующих различным управляющим состояниям.

1 Под < подразумевается отношение «является подтипом»

Существует широкий класс сущностей со сложным поведением, для которого модель разомкнутого ААТД оказывается непригодной. Во-первых, вычислительной мощности конечного автомата может быть недостаточно для описания выделенной разработчиком управляющей компоненты автоматизированного типа. Во-вторых, даже в том случае, когда логика поведения может быть описана конечным автоматом, в нем могут присутствовать группы «однотипных» состояний. Такие состояния не несут в себе уникальной информации, их можно различить, зная вычислительное состояние объекта автоматизированного типа. Наличие групп однотипных состояний свидетельствует о неправильном распределении обязанностей между управляющей и вычислительной компонентами.

В этих случаях можно ввести в ААТД обратную связь - позволить управляющему автомату получать определенные сведения о вычислительном состоянии и руководствоваться ими при вычислении управляющей функции. Напрямую оперировать значениями вложенного типа управляющий автомат не способен, поскольку их может быть бесконечно много. В связи с этим вводится конечное множество X наблюдаемых вычислительных состояний (или наблюдении), каждому из которых соответствует некоторая совокупность значений вложенного типа. Текущее наблюдение передается в качестве аргумента управляющей функции автомата.

На практике иногда требуется, чтобы текущее наблюдение зависело не только от вычислительного состояния, но и от аргументов вызываемого метода автоматизированного типа. При этом необходимо приписать собственное множество наблюдений Xe каждому событию. В дальнейшем будем рассматривать именно этот случай, так как он является наиболее общим.

Каким образом управляющий автомат опрашивает текущее наблюдение? Будем считать, что для каждого управляющего состояния s и события e ему известен предикат p - имя некоторого метода-наблюдателя2 вложенного типа, возвращающего текущее наблюдение. Отметим, что в настоящей работе управляющий автомат ААТД всюду предполагается детерминированным. Чтобы сохранить это свойство при наличии предикатов, необходимо потребовать, чтобы соответствующие им методы вложенного типа были однозначно специфицированы, т.е. чтобы их исполняющие функции имели вид f : D х {Obj : Args} {Obj : Ret} в некоторой известной области.

Автоматизированный абстрактный тип данных с обратной связью (рис. 3) назовем замкнутым по аналогии с замкнутой системой управления, которая также отличается от разомкнутой наличием обратной связи.

Рис. 3. Замкнутый ААТД

2 Наблюдателем (observer) называется метод, не изменяющий текущего значения 48

Определение 3. Замкнутым автоматизированным абстрактным типом данных будем называть пару (А,т), где А - управляющий автомат, т - вложенный абстрактный тип данных.

Управляющий автомат представляет собой восьмерку A = {S,E,X,Z,P,s0,K,A), где S - конечное множество управляющих состояний, Е - конечное множество входных символов (или событий), X = • Хе - конечное множество наблюдаемых вычисли-

ееЕ

тельных состояний (или наблюдений), Z - конечное множество действий, Р = • Ре -

ееЕ

конечное множество предикатов, s0 е S - начальное (стартовое) состояние, к : S хЕ —» Ре - функция предикатов, A :SxExXe^>SxZ - управляющая функция.

Пусть / - множество имен методов вложенного типа т , тогда Z а I, Р <z /, причем Ve е Е Хе = : maxmn(s e).Retj.

Для типов аргументов методов-предикатов действует то же правило контравари-антности, что и для методов-действий.

В заключение рассмотрения модели автоматизированного абстрактного типа данных отметим особенности ее практического применения для спецификации сущностей со сложным поведением. Во-первых, на практике действиям и предикатам автоматизированного типа не всегда бывает удобно сопоставлять ровно по одному методу вложенного типа (обычно их может быть любое количество). Во-вторых, правила сигнатур для методов-действий и методов-предикатов могут оказаться слишком сильными. Например, они запрещают методу-действию иметь меньше аргументов, чем имеет соответствующий метод автоматизированного типа, или, наоборот, иметь «лишний» аргумент, который в зависимости от состояния и события связывается с определенной константой. Обе эти проблемы решаются введением фиктивных методов-действий и методов-предикатов, которые удовлетворяют всем требованиям модели ААТД, но не обозначаются в спецификации и реализации в явном виде. Фиктивные методы строятся из действительных методов вложенного типа путем их композиции, последовательного вызова, связывания аргументов и других простых операций. Если фиктивный метод получается достаточно сложным, в целях улучшения ясности спецификации его следует оформить как отдельный действительный метод.

Спецификация ААТД

В этом разделе предлагается метод формальной спецификации автоматизированных абстрактных типов данных. Отметим, что при этом новой нотации не вводится -для полного описания ААТД достаточно объединить некоторый уже существующий язык спецификации конечных автоматов с выходами, с помощью которого будет описываться управляющая компонента, и некоторый язык спецификации абстрактных типов данных, с помощью которого будет описываться вложенный тип.

Для спецификации конечных автоматов в настоящей работе для простоты используются обыкновенные диаграммы переходов {state-transition diagrams, STD). Спецификации абстрактных типов данных выполняются на языке Larch [6]. Larch состоит из двух уровней, первый из которых используется для описания множеств значений типов, а второй - непосредственно для спецификации АТД. Синтаксис второго уровня Larch зависит от целевого языка программирования, для которого предназначена спецификация. В настоящей работе будем использовать упрощенный вариант Larch/C++

[7].

Спецификация абстрактного типа данных включает следующую информацию:

• имя типа;

• описание множества значений типа;

• для каждого из методов типа:

- имя метода;

- сигнатуру метода;

- семантику метода в терминах предусловий и постусловий.

Для иллюстрации предлагаемого метода спецификации ААТД рассмотрим классический пример сущности со сложным поведением - эмулятор турникета (Coin Machine) [8, 9]. Турникет принимает монеты любого достоинства. Если суммарной стоимости опущенных пользователем турникета монет достаточно для прохода, дверь открывается, и он может пройти. Если он опустил больше, чем нужно, турникет поблагодарит его, выведя соответствующее сообщение на экран. Если пользователь попытается пройти, не заплатив, турникет подаст сигнал тревоги. Кроме того, турникет может быть сломан, о чем также выводится сообщение на экран. Управляющая компонента турникета может быть описана с помощью диаграммы переходов, изображенной на рис. 4.

Coin Thankyou

T o

Рис. 4. Диаграмма переходов управляющего автомата Coin Machine

Из диаграммы переходов следует, что управляющий автомат турникета состоит из следующих компонент:

S = {Locked,Unlocked, Broken}, E = {Coin, Pass, Failed, Fixed}, X = XColn ={0,1} ,

Z = {Unlock, LockAndZero, Thankyou, OutOfOrder,InOrder, Alarm, Add},

P = PCoin = IsEnough,

s0 = Locked .

Множество наблюдений XCoin - это множество значений, возвращаемых предикатом isEnough. В том, что этот предикат действительно возвращает логические значения (и, следовательно, их можно использовать в булевом выражении, помечающем дугу диаграммы переходов), можно убедиться из приведенной ниже спецификации вло-женноготипатурникета Coin Machine Nested.

class CoinMachineNested {

spec bool doorOpen; // Открыта ли дверь

spec string msg; // Сообщение на экране

spec int sum; // Текущая накопленная сумма

spec const int cost; // Стоимость прохода public:

void Unlock() {

requires: true; modifies: doorOpen; ensures: doorOpen' == true;

}

void LockAndZero() { requires: true; modifies: doorOpen, sum;

ensures: (doorOpen' == false) && (sum' == 0);

}

void Thankyou() {

requires: true; modifies: msg;

ensures: msg' == "Thank You";

}

void OutOfOrder(string failure) { requires: true; modifies: msg;

ensures: (msg'.find("Out of Order") != string::npos) && (msg'.find(failure) != string::npos);

}

void InOrder() {

requires: true; modifies: msg;

ensures: msg' == "In Order";

}

void Alarm() {

requires: true;

}

void Add(int value) {

requires: value > 0; modifies: sum;

ensures: sum' == sumA + value;

}

bool IsEnough(int value) { requires: value > 0;

ensures: result == (sum + value >= cost);

}

}

В приведенном примере множество значений абстрактного типа описывается при помощи набора переменных спецификации [7]. В описании семантики методов ключевое слово requires обозначает предусловие. Постусловие представляет собой конъюнкцию выражения ensures и утверждения, что значения никаких объектов, кроме указанных в выражении modifies, не изменяются. Через хА обозначается значение объекта х перед началом исполнения метода, а через х' - в момент его завершения.

Связь между диаграммой переходов управляющего автомата и спецификацией вложенного типа обеспечивается идентичностью имен методов вложенного типа и со-

ответствующих им действий и предикатов на диаграмме. Если управляющий автомат имеет большое количество состояний и переходов, на диаграмме удобнее использовать сокращенные имена событий, действий и предикатов (например, ei, z{ и xi соответственно, как в нотации SWITCH). В этом случае для описания ААТД дополнительно понадобится словарь сокращений, отображающий связь между полными и сокращенными именами.

Отметим, что при рассматриваемом подходе к спецификации автоматизированных типов данных можно легко заменить обыкновенные диаграммы переходов диаграммами Statechart или графами переходов из SWITCH-технологии. С точки зрения последней, спецификация вложенного типа вместе со словарем сокращений заменяет и дополняет часть схемы связей автомата, отвечающую за связи с объектом управления. При этом вместо неформального описания предикатов и действий на схеме связей приводится их формальная спецификация в терминах пред- и постусловий. С точки зрения подхода Statemate спецификация вложенного типа представляет собой функциональный вид системы, т.е. заменяет Activity Chart.

В разд. 0 было показано, что автоматизированный абстрактный тип данных может быть преобразован в обыкновенный АТД. Описанный выше алгоритм преобразования можно переформулировать в терминах спецификаций. Таким образом, от спецификации автоматизированного типа, использующей нотации Larch и STD, можно перейти к спецификации на Larch. Результирующая спецификация будет описывать тип данных, поведения которого с точки зрения пользователя не отличается от поведения исходного автоматизированного типа.

Итак, пусть имеется автоматизированный абстрактный тип данных (A,t) (в общем случае замкнутый) с именем Name. Пусть диаграмма переходов задает вид его управляющего автомата A = (S, E, X, Z, P, s0, p, A), а спецификация вложенного типа т

задает его имя, множество значений, а также имена, сигнатуры и семантику его методов в терминах предусловий и постусловий. Предусловие метода с именем i будем обозначать mi.pre, постусловие - mi.post. В случае, если метод однозначно специфицирован и возвращает значение (напомним, что это справедливо для всех методов-предикатов), будем считать, что его постусловие содержит утверждение вида result = ret _ value . Таким образом, подстановка mi.post[v / ret _ value] будет означать, что возвращаемое методом значение равно v.

Построим спецификацию абстрактного типа данных т' следующим образом.

• В качестве имени т' выберем Name.

• Множество значений т' опишем как декартово произведение множества значений т и множества S . В частности, если множество значений описывается в терминах переменных спецификации, введем перечислимый тип а с множеством значений S . Тогда набор переменных спецификации типа т' будет содержать переменные из т и переменную state : а .

• Для каждого события e е E добавим к спецификации т' метод, такой что:

- имя метода совпадает с e ;

- сигнатура метода определяется по формулам

"k me Argsk = min т :: mp (se)Argsk ,mXn т :: mz (s,e, x)Argsk l seS V v ' ' xiXe y '

m„.Ret = max т :: mz (,ex).Ret;

e siS,xiXe z

семантика метода определяется по формулам:

me. pre = Ú

seS

'(stateA = s)лт :: mp(se).pre л л

me post =Л

seS

Ú

xeXe

r(stateA = s)^ ^

^ Л

- XeXe

Отметим, что в спецификациях типов в настоящей работе не рассматриваются формирователи (creators) - функции, создающие объекты данного абстрактного типа. Формирователи часто специфицируются отдельно от самого АТД, как, например, в работе [5]. При преобразовании автоматизированного абстрактного типа данных (А,т) в

обыкновенный тип c' спецификации формирователей С типа c' можно получить из спецификаций формирователей c типа c , изменив постусловия следующим образом:

С.post = c.post л (resu/t'.state = s0).

После преобразования автоматизированного типа данных в обыкновенный АТД теряется информация об управляющих состояниях или, другими словами, разделение описания логики сложного поведения и описания его семантики. Однако, если спецификация ААТД приведена к такому виду, для нее могут быть доказаны различные свойства и отношения, характерные для обыкновенных типов данных и определенные в терминах их спецификации. Если при рассмотрении этих свойств учесть потерянную информацию о состояниях, свойства абстрактных типов можно переформулировать в терминах ААТД и в дальнейшем использовать непосредственно.

Отношение наследования

Интуитивное требование к абстрактному типу данных, являющемуся наследником (подтипом) некоторого другого типа, выражается в Принципе подстановки Лисков (Liskov Substitution Princip/e, LSP). Он заключается в том, что объект подтипа может быть использован в программе везде, где ожидается объект супертипа. Этот принцип является общепризнанным, однако его смысл зависит от модели вычислений. В работе [5] приведены два формальных конструктивных определения отношения наследования в терминах спецификаций АТД на языке Larch, каждое из которых в некотором смысле удовлетворяет LSP. В настоящей работе ограничимся рассмотрением одного из них (использующего функцию расширения), поскольку оно требует меньше модификаций исходного языка спецификаций абстрактных типов данных.

Одним из существенных для пользователя атрибутов абстрактного типа c является его инвариант Ic - свойство значения xp, которое выполняется для любого объекта

X: c в любом вычислительном состоянии программы p . В [5] показано, что в отсутствие формирователей невозможно использовать индукцию для доказательства наличия у типа тех или иных инвариантов, поэтому предлагается обозначать инвариант в спецификации АТД в явном виде.

С учетом всего вышесказанного, определение отношения наследования через функцию расширения выглядит следующим образом.

Определение 4. Тип ш = (W,М) является подтипом (наследуется от) c = (T, N) (пишут ш< c ), если существует функция абстракции A :W  T, функция переименования R :М  N и функция расширения E :М х Obj*  Prog , такие, что: 1. выполняется правило инварианта: Vw e W 1ш (w) ^ Ic (A(w));

2. для каждого метода ш :: m е dom(R) и соответствующего ему метода т :: n = R (m) выполняется:

• правило сигнатур (разд. 0);

• правило семантики. Для всех объектов x : ш :

n.pre[ A(xA)/ xA] о m.pre, m.post ^ n.post[ A(xA)/xA, A(x')/x'];

3. для каждого метода w :: m £ dom(R ), значения его аргументов a : m.Args и объекта x: w должна быть определена программа prog = E (x.m(a)), обладающая следующими свойствами:

• prog принимает на вход набор объектов a и объект x;

• prog вызывает методы либо из dom(R ), либо методы типов, отличных от

ш ;

• пусть метод m и программа prog начинают выполняться в вычислительном состоянии программы р1, причем m.pre выполняется в р1, m завершает исполнение в р2, a prog - в y ; тогда A (x ) = A (xy ).

Рассмотрим теперь применение этого определения к типам т' и ш', построенным из автоматизированных типов данных (A1,^ и (Л2,ш^, соответственно (для простоты рассмотрим случай, когда оба ААТД разомкнуты). Управляющие автоматы автоматизированных типов имеют вид A1 = ^S1, E', Z', s0i, A^ , i = 1,2 . Их вложенные типы имеют вид т = (Г, N), ш = W,м>.

Чтобы тип ш' являлся подтипом т', во-первых, необходима функция абстракции A', соблюдающая инвариант. Из соображений разделения управляющей и вычислительной компонент ААТД, будем считать, что в данном случае эта функция может быть разложена на две составляющие - функцию абстракции вложенных типов A :W  T и функцию абстракции состояний S :S2  S1. Разумно считать, что инвариант автоматизированного типа данных совпадает с инвариантом его вложенного типа, поэтому правило инварианта можно сформулировать, используя только функцию A :

Vw е W 4 (W) ^ /т (a(W)).

Во-вторых, требуется функция переименования R :E2  E . Она может быть частичной, т.е. автоматизированный подтип может обрабатывать больше событий, чем его автоматизированный супертип. В-третьих, для всех E2 £ dom(R) требуется определить значение функции расширения E .

Рассмотрим теперь взаимосвязь между методом m с именем e типа ш' и соответствующим ему методом n с именем R (e) родительского типа т'. В соответствии с определением отношения наследования действует правило контравариантности аргументов вида

Vk n.Argsk < m.Argsk, или, в терминах аргументов методов вложенных типов,

Vk mS? nz 1 (s,r (e)) 'Argsk < mn mz 2(s,e).Argsk .

Таким же образом можно записать правило ковариантности результата:

m.Ret < n.Ret,

max mz ^ .Ret < max nz lf Dr x.Ret.

siS2 Z

Кроме того, для рассматриваемой пары методов m и n действует правило семантики. В соответствии с ним для любого объекта х : ш':

n.pre[A'(хЛ)/хл] о m.pre .

Обозначая через state управляющее состояние объекта х, а через y : ш вычислительную компоненту х, это выражение можно записать так:

v((S(^л) = s)л nzI(sR(e)).pre[ A(yл)/yл])о V ((^л = s)л mz2(se).pre).

seS1 seS2

Поскольку управляющее состояние может одновременно иметь только одно значение, из приведенного выше выражения следует:

" 6 S 2 mz 2^)^ ° Пс i( s( s),r (e)).pre[ A (УЛ)/УЛ] .

Аналогичные рассуждения можно привести относительно постусловий:

m.post ^n.post[A'(хЛ) /хл, A'(х')/х'],

л((stateл = s)^ (m^ 2 .post л (state' = 5 2(s, e))))^

seS?

a

seS1

"s e S2 mz 2(se).post ^ n .(s)R(e)).post[A(yA)/yA(y')/y'],

z 1 (s ( s ),r (e))'

и, кроме того, при абстракции состояний сохраняется функция переходов: "s e S2 S(52 (s, e)) = 5 45(s), R (e)) .

Наконец, рассмотрим функцию расширения. По определению, каждому событию e€e E2\ dom(R ), объекту x : ш' и набору значений аргументов a : m€.Args сопоставляется программа prog . В этой программе разрешается вызывать только «посторонние» методы или методы с именами e e dom(R ) . Поскольку каждый метод me на самом деле вызывает один из методов вложенного типа m 2 и вычисляет новое управляющее состояние, требование существования программы prog можно заменить следующим: "s e S2 $progs e Prog , такая что:

• progs вызывает только «посторонние» методы или методы вида m 2 , где e e dom(R ) ;

• пусть метод m 2 и программа progs начинают выполняться в вычислительном состоянии программы Pj, причем m 2pre выполняется в Pj, m 2 завершает исполнение в р2, а progs - в y ; тогда A (y ) = A (yy ) .

Исходя из приведенных рассуждений, можно сформулировать простое условие на автоматизированные типы (A1,!^ и {A2,w^j, достаточное для того, чтобы соответствующие им обыкновенные типы т 'и ш' были связаны отношением наследования в смысле определения Б. Дисков через функцию расширения. Это условие будем рассматривать как определение отношения наследования для разомкнутых автоматизированных абстрактных типов данных.

Определение 5. Разомкнутый ААТД (А2,ш^ (ш = (W,М)) является подтипом разомкнутого ААТД (А1,т) (т = (T,N), A = [s1 ,E',Z',s0',A1^), если существует функция абстракции состояний S :S2  S1 и функция переименования событий R :E2  E1,

такие, что:

2

J0

-г2

S (so2) = soJ

"s e S2 "e e dom(R ) S(52 (s, e)) = 5 J(S(s), R (e)) .

Кроме того, ш является подтипом t (в смысле определения через функцию расширения), и для их функции переименования R wt справедливо

е S2 "e е dom(R ) Rwt (Z 2(s, e)) = Z \S(s),R (e)).

Заключение

В работе подробно рассмотрено понятие автоматизированного абстрактного типа данных. По мнению автора, эта концепция наилучшим образом отражает объектно-ориентированный подход к моделированию сущностей со сложным поведением. ААТД представляет собой тип данных, логика поведения которого описывается конечным автоматом, а семантика - вложенным типом данных. Предложен метод спецификации автоматизированных типов данных, а также алгоритм преобразования описания ААТД в спецификацию эквивалентного ему обыкновенного типа. В работе подробно рассмотрено отношения наследования для типов со сложным поведением, предложено простое конструктивное определение этого отношения для разомкнутых автоматизированных абстрактных типов данных.

Попытки перенести свойства, характерные для абстрактных типов данных, на сущности со сложным поведением делались и раньше, например, в работе [10]. Однако эти свойства рассматривались в применении к конечным автоматам. С нашей же точки зрения, автомат - лишь одна из двух компонент сущности со сложным поведением, и если говорить о наследовании, композиции или обобщенности, то в применении именно к абстрактному типу, описывающему сущность целиком.

В дальнейшем автор планирует определить отношение наследования для замкнутых ААТД, а также рассмотреть применение к автоматизированных типам и их экземплярам других объектно-ориентированных техник моделирования и проектирования.

Литература

1. Хопкрофт Дж., МотваниР., Ульман Дж. Введение в теорию автоматов, языков и вычислений. М.: Вильяме, 2002. 528 с.

2. Буч Г., Рамбо Дж., Джекобсон И. Язык UML: Руководство пользователя. СПб: Питер, 2004. 430 с.

3. Harel D., Polity M. Modeling Reactive Systems with Statecharts. The Statemate Approach. New York: McGraw-Hill, 1998. 258 p.

4. Шалыто A.A. SWITCH-технология. Алгоритмизация и программирование задач ло-гическогоуправления. СПб: Наука, 1998. 628 с.

5. Liskov B., Wing J. Family Values: A Behavioral Notion of Subtyping // ACM Trans. Program. Lang. Syst., 1994.

6. Guttag J.V., Horning J.J. Larch: Languages and Tools for Formal Specification. New York: Springer, 1993. 571 p.

7. Leavens G.T. Larch/C++ An Interface Specification Language for C++ // http://www.cs.iastate.edu/~leavens/larchc++.html

8. Martin R. Three-Level FSM. Pattern Languages of Program Design, 1995.

9. Yacoub S.M., Ammar H.H. Finite State Machine Patterns. // Proceedings of EuroPLoP. 1998.

10. Sane A., Campbell R. Object-Oriented State Machines: Subclassing, Composition, Delegation, and Genericity. // Proceedings of OOPSLA. 1995.