nextupprevious

Next:1.10 Отражение
Up:1 Язык программирования Zonnon
Previous:1.8 Активности, поведение и взаимодействие


1.9 Программные единицы


Zonnon-программы представляются с использованием четырех конструкций (constructs), которые используются для формирования всей структуры программы: это – единицы module, object, definition  и implementation. Каждая конструкция может существовать как отдельно скомпилированная единица (separately compiled unit) или может текстуально встраиваться в содержимое другой конструкции. Между этими конструкциями выполняется ряд отношений, которые определяют, как они могут совместно использоваться; они представляют собой следующие типы отношений, где каждый x и y изображают некоторые конструкции:
 


Правила для допустимого использования конструкций (программных единиц) имеют следующий вид:

Представление допустимых отношений между конструкциями (программными единицами) можно преддставить в виде следующих пяти матриц (в них используются следующие обозначения: D = definition, I = implementation, O = object, M = module, +  =  отношение допустимо):
 

x/y D I O M           x/y D I O M               x/y D I O M
D                            D   +    + +                D
I                              I    +    + +                I     +
O                            O   +    + +               O    +
M   + + +               M   +    + +               M    +
x содержит y        x импортирует y     x агрегирует из y
 

x/y D I O M              x/y D I O M
D                              D   +
I    +                          I
O   +                         O
M   +                        M
x реализает y            x уточняет y
 
 
 

1.9.1. Модуль

Модуль (module) имеет двойственную природу: он определяет синтаксический контейнер для логически связанных объявлений и одновременно он определяет объект, чей жизненный цикл управляется системой. Таким образом, модуль обеспечивает механизм для текстуального разбиения исходной программы и также для динамической загрузки во время выполнения части программы в виде экземпляра объекта.

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

Module = module [ ModuleModifier] ModuleName [ ImplementationClause ] ";"
    [ ImportDeclaration ]
    ModuleDeclarations
    ( BlockStatement | end ) SimpleName.
ModuleModifier = "{" ident "}" // private или public.
ModuleDeclarations = { SimpleDeclaration | NestedUnit ";" }
    { ProcedureDeclaration | OperatorDeclaration }
    { ActivityDeclaration }.
NestedUnit = ( Definition | Implementation | Object ).
ImplementationClause = implements DefinitionName { "," DefinitionName }.
ImportDeclaration = import Import { "," Import } ";".
Import = ImportedName [ as ident ].
ImportedName = ( ModuleName | DefinitionName | ImplementationName | NamespaceName |
    ObjectName).

Каждый module имеет уникальное имя и состоит из текста, который может отдельно быть скомпилирован как единица. Факультативно module может реализовывать одно или больше definition. В этом случае различные аспекты объекта раздельно определяются в единицах definition, которые поддерживают абстрактный интерфейс. Факультативно module может импортировать элементы из одной или нескольких implementation, что означает получение доступа к их областям действия и возможности агрегирования их содержимого. Используя предложение as, также возможно переименовать все объекты при их импортировании. Это можно использовать для предотвращения конфликтов имен и/или упрощения длинных внешних имен для повышения программной читаемости.

Пример:

import System.Console as S;

S.WriteLine('Hello'); (*эквивалентно System.Console.WriteLine('Hello') *)

Модуль факультативно может содержать
 


Примеры:

module Small;
begin
     write ('Hello World')
end Small.

module BodyMassIndex;
    (* вычислить индекс массы тела *)
    var height, weight, bmi: real;
begin
    write('weight in kg? '); read(weight);
    write('height in m? '); read(height);
    bmi := weight / (height * height);
    write(' body mass index is', bmi : 6: 2);
    if bmi < 19 then
        write('too thin')
    elsif bmi < 27 then
        write('OK')
    else
        write('too fat')
    end
end BodyMassIndex.

definition D; …end D.

definition E; …end E.
module M;
import D, E;
    var a: object{D, E}; (* один объект, который реализует как D, так и E *)

end M.
 

1.9.2. Объект как единица программной композиции

Факультативно объект может реализовать одну или более definitions. В этом случае различные аспекты объекта определяются отдельно в единицах definition, которые обеспечивают абстрактный интерфейс. Также объект может импортировать элементы из module или implementation, т.е. получить доступ к их областям действия. Используя предложение as также возможно переименовать все элементы, когда они импортируются. Это можно использовать для предотвращения конфликтов имен и/или упрощения длинных внешних имен для повышения программной читаемости при программировании внутри объекта.
Заметим, что объект, импортирующий определение D для того, чтобы использовать реализацию D должен явно агрегировать ее, импортируя D, см. разделы 1.9.3 и 1.9.4.

 

1.9.2.1. Наследование: уточнение и агрегирование

Имеется два вида наследования (inheritance) в языке Zonnon: уточнение (refinement) и агрегирование (aggregation). Уточнение является наследованием некоторого определения интерфейса, в то время как агрегирование является наследованием (переиспользованием) (фрагмента) существующей реализации. Предполагается, что все определения объектов, которые явно не уточняют некоторый другой объект, уточняют object. Таким образом, все объекты (прямо или косвенно) уточняют object. Если некоторый объект B уточняет объект A, то говорят, что B является “происходит из” A.

1.9.2.2. Кратное наследование

 
Кратное наследование (multiple inheritance) характеризуется возможностью уточнения нескольких определений и/или агрегирования нескольких реализаций. В языке Zonnon отсутствует неоднозначность, связанная с кратным наследованием, поскольку в нем используются квалифицированные идентификаторы для именования (См. 1.3.1).

1.9.2.3. Полиморфизм

 
Полиморфизм (polymorphism): который в общем случае включает выбор подходящего метода для вызова во время выполнения в зависимости от типа переменной, которая должна быть задействована. Имеются две концепции:
1) здесь требуется некоторый объект типа T, и
2) здесь требуется некоторый объект, который реализует определение интерфейса D
Язык Zonnon делает основной упор на второй более общей концепции, причем и идет дальше, разрешая спецификацию кратных определений (так называемые аспекты (facets) полного интерфейса объекта) и таким образом в этом контексте полиморфизм означает, что «здесь требуется некоторый объект, который реализует D1и D2 и …».

 

1.9.3. Определение


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

Definition = definition [ DefinitionModifier] DefinitionName [ RefinementClause ] ";"

[ ImportDeclaration ]

DefinitionDeclarations

endSimpleName.

DefinitionModifier = "{" ident "}" // private или public

RefinementClause = refines DefinitionName.

ImportDeclaration = import Import { "," Import } ";".

Import = ImportedName [ as ident ].

ImportedName = ( ModuleName | ImplementationName | NamespaceName |

DefinitionName| ObjectName).
DefinitionDeclarations = { SimpleDeclaration } { { ProcedureHeading ";" } | ActivitySignature }.
 
 

Definition имеет уникальное имя и факультативно уточняет (refines) другое definition, представляя новый аспект объекта, возможно добавляя поля и поведение и, таким образом, формируя специальную форму исходного определения.

Оно может также факультативно импортировать (import) элементы из одного или более implementation, что дает доступ к их области действия и делает возможным литеральную агрегацию их содержимого. Используя предложение as также возможно переименовать все элементы, когда они импортируются. Это можно использовать для предотвращения конфликтов имен и/или упрощения длинных внешних имен для повышения программной читаемости при программировании внутри объекта. Модификаторы public и private могут использоваться для объявления видимости содержимого определения. Если модификатор не представлен, то по умолчанию выбирается public. Definition может содержать множество объявлений констант, типов и переменных, а также заголовков процедур методов (сигнатур), но не тел процедур.

Примеры:
 
 

definitionGraphical;

(* свойства всех графических объектов *)

varx, y: integer; (* object’s position *)

procedureMoveTo (newX, newY: integer);

(* post: (x = newX) & (y = newY) *)

procedureMoveBy (dx, dy: integer);

procedureDraw;

endGraphical.

definitionRectangle refines Graphical;

(*свойства, специфические для прямоугольных объектов *)

varwidth, height: integer;

procedureArea ( ): integer;

endRectangle.

implementationGraphical;

(*см. Пример в разделе 1.9.4 *)

endGraphical.

object{ref} Box implements Rectangle;

procedureArea ( ): integer;

begin

returnwidth * height
endArea;
 
 

1.9.4. Реализация


Реализация (implementation) определяет агрегат фрагментов полей и реализаций методов, предназначенных для переиспользования, при включении в программу посредством одного или нескольких образцов объектов. Реализация имеет уникальное имя, если она не имеет то же имя, что соответствующее определение (definition). Она факультативно может импортировать (import) элементы из одной или нескольких других реализаций (implementations), т.е. получать доступ к их областям действия и иметь возможность агрегировать их содержимое. Используя предложение as также возможно переименовывать все элементы при их импорте. Эта возможность может быть использована для ликвидации конфликтов имен и/или для упрощения длинных внешних имен, что повышает наглядность при программировании внутри объекта. Модификаторы public и private могут быть использованы для объявления видимости содержимого реализации. Если нет модификатора, по умолчанию выбирается модификатор public.

Object, реализующий definition, должен реализовывать все его методы, если это определение не имеет соответствующей реализации, которая импортируется данным объектом. Однако, если объект импортирует implementation некоторого definition с тем же именем, то предполагается, что он  является его (возможно частичной) реализацией.
 
 

Implementation = implementation [ImplementationModifier] ImplementationName ";"

[ ImportDeclaration ]

Declarations

( BlockStatement | end ) SimpleName.

ImplementationModifier = "{" ident "}". //private или public

ImportDeclaration = import Import { "," Import } ";".

Import = ImportedName [ as ident ].

ImportedName = ( ModuleName | ImplementationName | NamespaceName |

DefinitionNameObjectName ).
 
 

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

Примеры:

implementationGraphical; (* реализация definitionGraphical *)

(*X и Y объявлены в определении*)

procedureMoveTo (newX, newY: integer);

begin

x := newX; y := newY

endMoveTo;

procedureMoveBy (dx, dy: integer);

begin

x := x + dx; y := y + dy

endMoveBy;

endGraphical.
 
 
 
 

Next:1.10 Отражение
Up:1 Язык программирования Zonnon
Previous:1.8 Активности, поведение и взаимодействие


© В.Н. Касьянов, Е.В.Касьянова,2004