PROGLANG (1129115)
Текст из файла
Глава 2 Модульность, инкапсуляция, раздельная трансляция
Модульность
-
Модуль – это то, что легче заимствовать, чем написать заново.
Разделяют логическую структуру и физическую структуру модуля.
В С можно выделить следующие типы модулей:
-
библиотека процедур;
-
модуль-объект;
-
модуль-тип данных;
-
смесь.
Инкапсуляция означает ограничение доступа данных.
Абстрактный тип данных (АТД) – это тип данных, в которых инкапсуляция максимальна. Поэтому абстрактный тип данных это только множество операций, определенных пользователем. Любые языки, которые имеют операции над указателями, позволяют взламывать защиту.
Программа на Модуле-2 представляет собой:
Главный модуль + Библиотечный модуль
интерфейс тело
(модуль определений) (модуль реализаций)
Локальный модуль может быть внутри другого, но в Обероне Вирт отказался от локального модуля. Стандартная схема разделения определения, реализации и использования (РОРИ) задает схему программирования снизу вверх (Модула-2 заставляет писать в линеечку).
DEFINITION MODULE имя
FROM имя_модуля IMPORT список_имен;
список _объявлений;
END имя.
Можно импортировать все имена из модуля
IMPORT имя_модуля;
но тогда все имена надо будет квалифицировать по полной программе: имя_модуля.имя.
IMPLEMENTATION MODULE имя;
списки_импорта;
объявления/определения;
[BEGIN
операторы ]
END имя.
Тело может отсутствовать, а определения видны только внутри модуля.
В Turbo Pascal модуль определений и реализаций слиты воедино в понятие Unit.
unit имя;
interface
...
implementation
...
[begin
операторы]
end.
В Модула-2 есть понятие скрытого типа данных opaque. Если объявляется новый тип без указания базового, то считается закрытым.
TYPE имя;
Работать с такими типами можно только через объявленные функции в модуле определений.
DEFINITION MODULE STACKS
TYPE STACK;
PROCEDURE INIT (VAR S : STACK);
PROCEDURE PUSH (VAR S : STACK; X : INTEGER);
PROCEDURE POP (VAR S : STACK) : INTEGER;
END STACK.
MODULE M
IMPORT STACKS;
VAR A : STACKS.STACK;
BEGIN
STACKS.INIT (A);
STACKS.PUSH (A,1);
...
END M.
Но из-за простоты скрытый тип данных становится ущербным, компилятор не может произвести распределения памяти, так как нет модуля реализаций. Следовательно, единственная возможность: скрытым типом может быть только либо тип pointer, либо integer. Таким образом вся скрытость летит в полную горбатость. Теперь у программиста будет болеть голова: как же ему реализовать стек, чтобы элементы были либо pointer либо integer?
IMPLEMENTATION MODULE STACKS;
...
TYPE StackRec = RECORD
B : ARRAY [1..StackSize] OF INTEGER;
TOP : [1..StackSize];
END;
STACK = POINTER TO StackRec;
END.
Но кто за нас проинициализирует TOP на единицу, отведет память под массив? Для этого необходимо по старинке вызывать функцию INIT. А кто проконтролирует нас, что мы проинициализируем STACK и отведем память, Таким образом простота приводит к концептуальной бесполезности АТД в Модуле-2. Поэтому такой красивый язык не прижился, но профессор Вирт двинулся дальше и уже работал над Обероном.
В Обероне программа представляет собой такой текст, который нельзя использовать сразу без некоторых инструментов. Вместо 4-х типов модулей в Обероне только 1 тип модуля.
MODULE имя;
определения
[BEGIN
операторы]
END
Для того, чтобы экспортировать имя, надо при его определении ставить * после него
TYPE STACK* = RECORD
B : ARRAY[1..StackSize] OF INTEGER;
TOP : [1..StackSize];
END;
PROCEDURE PUSH* (...);
PROCEDURE POP* (...);
PROCEDURE INIT* (...);
...
Чтобы вытащить интерфейс из такого модуля – запарился, поэтому в Обероне есть инструмент, который проходит по тексту и выделяет интерфейс в модуль определений, осуществляет проекцию. При этом те имена, после которых стоят *, сгруппируются в файл определений (интерфейса).
DEFINITION MODULE STACKS
TYPE STACK = RECORD END;
PROCEDURE PUSH (...);
...
END STACKS.
Вот вам и закрытый тип данных, то есть с реализацией АТД проблем не будет. Мы можем контролировать доступ к переменным. При этом механизме
... = RECORD
F1 : T1;
F2*: T2;
F3 : T3;
END;
спроецируется в
... = RECORD
F2 : t2
END;
Модульная структура в Ada основана на понятии пакет, при этом используется принцип разделения определения и реализации.
П
акет спецификация
тип пакета
package имя_пакета is
объявления;
... объявление
[приватная часть]
end имя_пакета;
package body имя_пакета is
объявления/расширения;
[ begin реализация тела
опрераторы]
end имя_модуля.
Если убрать информацию о раздельной компиляции, то модули на Ada можно слить в один. Ada позволяет использовать вложенные пакеты.
package P1 is package body P1 is
... ...
package p2 is package body P2 is
... ...
end P2; end P2;
... ...
end P1; end P1;
Тела пакетов закрыты, поэтому можно экспортировать имена, описанные только в объявлении. Доступ к именам осуществляется путем квалификации имени через точку, но они потенциально видимы только после конца описания пакета. Вспомним, что Ada может переопределять (перекрывать) функции.
type T is ... function «+»(X,Y : T) return;
...
x,y : P.T;
z : P.T;
Но писать прямо z:=x+y; – нельзя, а надо: z:=P.«+»(x,y);. Естественно, вся прелесть перекрытия улетучивается, поэтому возникла необходимость другого механизма видимости имен. После спецификации нужно указать
use список_модулей;
Таким образом после этой конструкции можно красиво писать z:=x+y;. Если два пакета P1 и P2 вложены и в P2 определен x, то после строк
use P1;
use P2;
имя x становится видимым.
В Turbo Pascal все модули равноправны, и если два имени объявлены в двух модулях, то оба имени становятся невидимыми (если нужен доступ, надо квалифицировать имена) и все становится просто. А в Ada из-за огромного нагромождения простых в принципе правил, да еще плюс иерархия какая-то, можно просто сломать ногу и проломить черепную коробку.
Инкапсуляция
Для реализации АТД необходима инкапсуляция, сокрытие данных, для этого нужно воспользоваться механизмом приватной части
package Stacks is
type Stack is private;
procedure Push (S : inout Stack; X : in integer);
procedure Pop (S : inout Stack; X : out integer);
private:
type Stack is record
B : array [1..100] of integer;
T : integer range 1..100 := 1
end record;
end Stacks;
Здесь можно воспользоваться возможностью сделать начальное присваивание, миниинициализация.
В С++ функции логического модуля выполняет класс, а концепция физического модуля (файл) в принципе отсутствует. Мы знаем, сто в С++ существует 3 уровня доступа к данным: public, protected и private. Для того, чтобы иметь доступ к закрытым полям данных существует механизм дружественного доступа. Класс может разрешить классу не наследнику или посторонней функции получить доступ к своим полям.
class X{
...
friend class Y
или
friend прототип_функции;
...
}
Но friend – это не «дырка» в концепции языка, потому что дети класса Y уже не смогут пользоваться полями X, только сам класс Y.
Раздельная трансляция
Различают следующие виды трансляции:
1. Пошаговая трансляция;
2. Инкрементная трансляция (JIT – для Java байт-кода);
3. Цельная трансляция;
4
. Раздельная трансляция независимая
зависимая
Следует понимать два контекста: стандартный и пользовательский.
из встроенных таблиц из объявлений в программе
Независимая компиляция
В качестве абстракции выступает процедура или функция, а конкретизация означает – собственно вызов процедуры или функции. Связь между абстракцией и конкретизацией происходит статически, а виртуальные методы связываются динамически. Типы данных и объект связываются статически во всех языках, кроме Lisp и некоторых реализаций Basic. В объектном коде содержится необходимая информация об именах
имя | класс | размер | доступ
| |
данные/команды общий/закрытый
Связь производится компоновщиком (редактором связей) на последнем этапе, и все link-еры умеют работать только с этой моделью объектного кода (начиная с 50-х годов). Вот и мучаются программеры всего мира с именами своих объектов.
Из-за того, что в С подключаемый модуль может описывать
тип данных;
набор функций;
набор операций.
А включающий модуль содержит копии описаний типов и констант, то в С пролазит понятие структурной эквивалентности. Для удобства программирования на С впоследствии вынуждены были появится такие утилиты, как make и lint.
Зависимая компиляция
Зависимая компиляция подразумевает одностороннюю связь между модулями
Программная библиотека
главный модуль
библиотечный модуль
(стандартный контекст)
.def+.mod+.obj
Трансляционная библиотека
модуль определений

(пользовательский контекст)
Недостаток зависимой компиляции – это плохая поддержка программирования снизу вверх.
Для описания импортируемых имен нужно воспользоваться констукцией
with <список_имен>; [use <список_имен>;] ...
Это односторонняя связь: экспортер не знает ничего о клиентах, а импортер должен точно указывать своих экспортеров. Можно описать двустороннюю связь
package P is
...
end P;
...
package body P is
procedure T() is separate;
package P1 is separate
...
end P1;
...
end P;
Теперь где-нибудь потом можно написать тело пакета и функции
separate (P) procedure T is
...
end T;
separate (P) package body P1 is
...
end P1;
Это позволяет программировать сверху вниз
Глава III Управление последовательностью выполнения
программ
В 1968 году статья Дейкстры всемирно обругала оператор goto. Дейкстра утверждал, что для структурного программирования нельзя использовать этот оператор, так как каждый элемент структурированной программы должен иметь строго один вход и строго один выход. При этом он говорил, что достаточно для программирования следующих конструкций
while E do s
if e then s
if e then s1 else s2
case
repeat
Характеристики
Тип файла документ
Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.
Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.
Файлы такого типа обычно разбиты на страницы, а текст может быть форматированным (жирный, курсив, выбор шрифта, таблицы и т.п.), а также в него можно добавлять изображения. Формат идеально подходит для рефератов, докладов и РПЗ курсовых проектов, которые необходимо распечатать. Кстати перед печатью также сохраняйте файл в PDF, так как принтер может начудить со шрифтами.