Главная » Просмотр файлов » лекции (1998) (Буров)

лекции (1998) (Буров) (1161123), страница 12

Файл №1161123 лекции (1998) (Буров) (лекции (1998) (Буров)) 12 страницалекции (1998) (Буров) (1161123) страница 122019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 12)

связывается с операцией доступа по полю: X.Re=…

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

Заметим, что мы хотели данным типом описать комплексное число, которому, вообще говоря, соответствует не только определенное множество значений, но и определенный набор операций (+, -, * и .т. д.). Если мы захотим описать это на ЯП Pascal, то встает два вопроса: а) как логически связать тип данных с соответствующим набором операций? б) насколько естественно впишется новый тип в структуру языка, действительно ли это будет расширением или же некий полиотип? В стандартном Pascal ответ на эти оба вопроса будет отрицательный, так как в нем полностью отсутствуют средства, позволяющие связывать множество значений и набор операций, следовательно о втором вопросе говорить даже не приходится.

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

Давайте по очереди рассмотрим, как реализованы эти логические модули в различных ЯП. Про стандартный Pascal мы ничего сказать не можем, точно также мы ничего не можем сказать о языке С, в нем тоже отсутствуют механизмы логического группирования.

Поговорим о модульной структуре языков и о том, как она применяется для формирования новых типов. Начнем с самых простых вариантов, созданных профессором Виртом: Модула-2 и Oberon.

В Модула-2 существует три вида модулей:

  • главный (некий аналог функции main), он может быть только один.

MODULE имя;

Набор определений;

BEGIN

Набор операторов;

END имя;

  • библиотечный (он будет интересовать нас больше всего, т.к. одно из его предназаначений - введение новых типов данных)

  • локальный модуль (обязательно вложен либо в набор определений главного модуля, либо в процедуру)

Библиботечный модуль разделяется на две части:

  • модуль определений

  • модуль реализаций

Эти два модуля имеют одинаковое имя, но различную структуру. Модуль определений служит для того, чтобы показать интерфейс модуля (каждый модуль имеет интерфейс для связи с внешним миром) – это набор имен и их свойств (атрибуты, если это тип данных; тип, если это переменная; значение, если константа и т.д.), которые видны извне этого модуля, т.е. только этими именами можно пользоваться. Напишем модуль определений, который реализует модуль Stacks (он представляет некий механизм работы со стеками):

DEFINITION MODULE Stacks;

Type Stack =

RECORD

Body: ARRAY [1..50] OF CHAR;

Top: 1..51;

END;

PROCEDURE PUSH (VAR S: Stack; X: CHAR);

PROCEDURE POP (VAR S: Stack): CHAR;

VAR errcode: INTEGER;

PROCEDURE INIT (VAR S: Stack);

END Stacks.

В этом модуле мы указываем только прототипы. На случай, когда у нас возникает ошибка (например, переполнение стека) мы вводим переменную errcode, которая фактически является частью типа, а с другой стороны – ему не принадлежит. Такие переменные называются членами класса, она принадлежит одновременно всем переменным класса. В C++ и Java такие переменные называются статическими. В этой переменной «сидит» последний код ошибки.

Процедура INIT инициализирует стек. Тем самым мы ввели новый тип и набор операций над ним.

IMPLEMENTATION MODULE Stacks;

{ Определения процедур и функций из Defenition Module

Здесь также могут быть и другие дополнительные определения}

[ BEGIN

Операторы; Errcode=0;

END Stacks. ]

Часть в квадратных скобках может отсутствовать. В качестве инициализации мы сопоставляем переменной Errcode Значение 0. Эта инициализирующая часть выполняется лишь один раз в момент загрузки модуля. Обычно она очень короткая или может вообще отсутствовать.

Зачем нужен модуль реализации? Зачем выделять его отдельно? Дело в том, что все, что находится внутри модуля реализации недоступно извне. Программист, использующий конкретный библиотечный модуль имеет доступ только к определениям, описанным в интерфейсной части. Это есть некое управление доступом. Позже мы заметим, что такое разделение имеет отношение еще и к механизму раздельной компиляции в ЯП Модула-2. Что нужно компилятору, чтобы корректно откомпилировать клиентский модуль (модуль, использующий Stacks)? Ему нужен только модуль определений, так как в нем есть все необходимые данные. Модуль реализации нужен лишь для того, чтобы собрать готовую работающую программу. Заметим, что Н.Вирт убил здесь сразу нескольких зайцев.

В Turbo Pascal, например, такого разбиения на два модуля нет, там две части – объявления и реализация объединены в одной физической части:

Unit имя;

Interface

{…}

implementation

{…}

end.

Можно ли упростить эту схему? Рассмотрим язык Oberon. Вирт для создания этого языка выкинул из Modula-2 все не необходимые вещи, то есть еще минимизировал этот и без того простой язык и добавил одну концепцию, а именно, концепцию расширения функций. Что выкинул Вирт? Деление на две физические части, понятие локального модуля и понятие главного модуля. В Обероне отсутствует понятие главного модуля вообще. В нем есть только одно понятие – модуля.

MODULE имя;

Набор определений;

BEGIN

Инициализация

END имя.

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

У возникшей проблемы есть некоторое решение. Дело в том, что современные ЯП представляют из себя не столько компилятор, сколько интегрированную среду, включающую в себя редактор, компилятор, управление проектами, помощью и т.д. И с этой точки зрения в Обероне принято следующее – у нас есть только один модуль, например:

MODULE Stacks;

TYPE Stack * =

RECORD

Top: INTEGER;

Body: ARRAY 50 OF CHAR;

END;

PROCEDURE PUSH * (VAR S: Stack; X: CHAR);

END Stacks;

Звездочка после имени говорит о том, что имя является экспортируемым.

Что хорошо и что плохо?

Хорошо то, что мы освобождаемся еще от одного языкового понятия. И еще (этого нельзя сделать в Модула-2), заметим, что у Top и Body отсутствуют звездочки, это говорит о том, что тип данных Stack доступен только через свое имя и экспортируемый набор операций. То есть мы упрятали поля Top и Body от несанкционированного доступа. Заметим, что в Модула-2, если мы что-то сделаем с элементом Top, то стек испортится. Здесь же мы имеем очень хорошую и естественную защиту от случайной порчи. К тому же, можно давать доступ к отдельным полям записи.

А плохо то, что если иметь маломальски нормальный модуль, то разобраться по тексту, что там происходит, что экспортируется, а что нет – весьма тяжело. От этой проблемы нас как раз и избавляет интегрированная среда Oberon’а, которая включает в себя средство генерирования модуля определения. По нашему модулю она выдаст следующее:

DEFENITION Stacks;

TYPE Stack = RECORD END;

PROCEDURE PUSH;

END Stacks;

И далее можно пользоваться только вот этим сгенерированным модулем определений. Это решение тоже влечет некоторые недостатки с точки зрения раздельной компиляции. Но об этом будем говорить позже.

Перейдем к языку Ada. Мы начали с простых схем – языков Pascal, Modula-2, Oberon. Ada представляет некоторое усложнение. В нем существует понятие логического модуля, которое называется Package:

Package Stacks is

Record

Body: array (1..50) of character;

Top: 1..51;

End record;

Procedure Push(S: inout Stack; X: character);

Procedure Pop(S: inout Stack; X: out character);

End Stacks

Процедуру Pop, вообще говоря, следует описать как функцию, но тут есть один ньюанс: в Ada функции могут иметь только IN параметры, а в нашем случае параметр типа Stack следует передавать, как INOUT.

Заметим, что, не считая синтаксической разницы, мы получили в чистом виде модуль определения языка Modula-2. И, следовательно, должна быть конструкция, которая идейно соответствует модулю реализаций, где будут конкретизироваться процедуры и функции, а также будут вводиться какие-то данные (типы, процедуры и т.п.) необходимые для внутренней реализации. Такая конструкция есть и называется она «Телом пакета»:

Package body Stacks is

end Stacks;

Несмотря на похожесть с Modula-2 в Ada имеются и различия (с точки зрения организации доступа, плюс некоторые усложнения). Дело в том, что в Ada существуют так называемые «локальные пакеты». Уже было сказано о локальных модулях в Modula-2 – это крайне ограниченная конструкция, он имеет следующий вид:

MODULE имя;

EXPORT список имен;

Определения

BEGIN

Инициализация

END имя;

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

В Ada ситуация немного другая, мы можем создавать вложенные пакеты:

package M is

package M_IN is

end M_IN;

end M;

Причем вложенный пакет имеет свой нормальный интерфейс и свое тело, причем тело будет реализовано по структуре там же, где и описание:

package body M is

package body M_IN is

end M_IN;

end M;

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

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

Сверху вниз:

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

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

С точки зрения модульной организации Modula-2 соответствует больше схеме “снизу вверх”, потому что мы, например, не можем откомпилировать программу, использующую модуль Stacks, если он еще не готов. Поэтому в данном случае мы над базсисом постоянно надстраиваем более общие конструкции.

Ada же предоставляет возможности работы, как «снизу-вверх», так и «сверху-вниз». Таким образом Ada – технологически более преимущественный язык, но с другой стороны – оправдываются ли эти преимущества усложнениями? Вопрос интересный.

Заметим, что все эти языки без наследования. Каким образом можно эмулировать наследование в языке, где его нет? Видимо, как раз с помощью локальных модулей. На этом мы пока закончим с языком Ada. Мы не обсуждали еще вопросы видимости и раздельной компиляции – это тема для будущих рассуждений.

Поговорим про языки C++ и Java. Чем хорош C++? В нем назначение модуля не сводится только к определению типа данных, хотя может к нему сводиться, но модули могут использоваться и для других целей. Одно и преимуществ – нам не надо придумывать два похожих имени для типа данных и его “обертки” – модуля. Очевидно, мы должны задавать различные имена, но это – накладной расход.

Концепция классов в C++ и Java свободна от этих недостатков: класс управляет правами доступа, видимостью. С другой стороны класс – это тип данных. То есть «фантик» и содержимое в одном флаконе. Общее определение класса в C++ имеет такой вид:

class имя {

определения членов класса

};

строго говоря, если мы будем компилировать программу на С, используя компилятор C++, то мы окажемся в положении мольеровского господина Журдена, который обнаружил, что всю жизнь говорил прозой. Ибо окажется, что мы всю жизнь программировали в терминах классов, сами того не замечая. Дело в том, что новую концепцию классов оказалось возможным совместисть со старой концепции структуры. Дело в том, что определения класса и структуры в C++ эквивалентны во всем за исключением области прав доступа.


struct S {

}

по умолчанию все элементы класса являются приватными (недоступными), а структуры – доступными, если не указано обратного.

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

struct stack {

Характеристики

Тип файла
Документ
Размер
1,12 Mb
Тип материала
Высшее учебное заведение

Список файлов лекций

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6352
Авторов
на СтудИзбе
311
Средний доход
с одного платного файла
Обучение Подробнее