лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел), страница 7
Описание файла
PDF-файл из архива "лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 7 страницы из PDF
за это время изменились взгляды программирования)••••наследованиекомпозицияреференцияделегирование (передача использования части интерфейса)В оберон-2 было понятие наследования, при этом наследовалась структура типа (поля класса). Безпроцедурного типа невозможно полностью реализовать объектную концепцию.[lect19] Подпрограммные ТД• передача параметров• делегированиеСначала рассмотрим подпрограммные ТД как указатели. В таком случае фактически передаем только адресначала массива данных, затем выполняем call, к таким языкам относятся: C, C++, Паскаль, М-2, Оберон,Delphi, Ада95.М-2, Оберон, Delphi:type PRCi = procedure( integer );Такие конструкции появились, когда понадобилась связь с другими подпрограммами, т.е. нужно былопередавать адреса процедур и функций.Ада95:type PRCi is access procedure PRC(i: integer);procedure PP(a: integer);procedure FCALL(P: PRCi) isbeginP();end FCALL;Попытки повысить гибкость языка за счет передачи адресов функций провалилась т.к.
все эти языкипроисходят от Фон-неймановских языков. Особняком стоят только С++ и Delphi так как в них есть понятиекласса (а также процедуры и функции члены класса), а в остальных есть понятие контейнера.C++, Delphi:void Foo(int);typedef void (*Footype) (int);Footype f;f = Foo;Теперь мы можем вызывать Foo так: *f(0) или так: f(0)class Bar{void Foo(int);int i;};int Bar::*pB;pB = &Bar::i; //так нельзяBar b;pB = &b; //а вот так можноvoid (Bar::*)Foom(int);Foom f;f = Bar::foo;Для обращения к указателю на член класса используются операторы: .* и ->*.
То же самое, но с другимсинтаксисом присутствует и в языке Delphi. Т.е. отдельно существует функциональный тип и тип, которыйреализует указатели на члены класса.Java:В Java нет понятия функционального типа. Т.е. нельзя передавать указатели на функции. Полезныйпример, где нужно передавать указатели на функции: вычисление интеграла.class Integral{public double IF(double){…}public double Integrate(double a, double b, double EPS){…}Т.е. все, что нам надо – это унаследоваться от класса Integral и перегрузить функцию IF, в дальнейшемпроцедура Integrate будут вызывать уже нашу функцию. Есть другой способ.class FuncBar{public FuncBar(Bar b){ _b = b; }private Bar _b;public void Caller(int){ _b.Foo(i); }Так как указатель слишком низкоуровневая штука и, как следствие, она небезопасна, то ее и убрали изJava.
Как видим, без этого можно обойтись.С#:public delegate void Operation(int);//это прототип, в этот delegate входят все функции, которые имеют такой типpublic Operation dlgt;class Bar{public void Foo(int x){…}public static void Foo2(int i){…}Bar b;dlgt = new Operation(b.Foo); //можно такdlgt = new Operation(Bar.Foo2); //а можно и так, указатели на разные функцииВ delegate включается не только указатель на объект, но и указатель на член функцию. Для delegateопределены также операции += и -= (фактически это просто вызовы static-функций из классаSystem.Delegate). Это значит, что delegate – это целые «цепочки».
Изначально delegate инициализируетсяпустым значением.dlgt += new Operation(b.Foo);dlgt += new Operation(Bar.Foo2);class X{ public void f(int a); }dlgt += new Operation(new X().f); //т.е. не важно какие функции, какого типаОт delegate можно определить массив функций и вызывать их отдельно. Т.е. delegate – просто болеекороткий синтаксис. Специально для callback в С# есть особые delegate – механизм событий. Есть операцииsubscribe, unsubscribe и distribute, т.е.
мы подписываемся на некое событие, а когда оно происходит, насуведомляют. Пример: таймер, почтовые сообщения.Также в языке C#, начиная с версии 2.0, появились анонимные делегаты.public delegate int Operation2(int x, int y);Operation2 op = delegate(int x, int y) { return x + y; };int i;op = delegate(int x, int y) { return x + y + i; }//в качестве контекста можно использовать даже локальные переменные,//это называется «захват» или замыканиеЗаметим, что в C# нет функций как таковых, а есть static (или просто) челны класса.Delegate int Oper0();Oper0 0;Public Delegate[] Create() {Oper0[] ops = new Oper0[3];int i = 0;for(int k = 0; k < 3; k++) ops[i] = delegate(){ return i++; }return ops;}Вопрос: что напечатается, если вызовем Create? (0, 1, 2), если i описана как в примере, и (0, 0, 0) если она«совсем локальная» (переместить).
Также делегаты можно использовать для Binder. Более общее и«приятное» понятие, заменяющее анонимных делегатов (покрывающее, более общее) – лямбда-выражения(введены в 2008 в С#, известны очень давно).[lect20] Средства развития ЯПГлава 5. Логические модули в традиционных ЯП. Определение новых ТД с помощью ЛМI) Понятие ЛМЛогический модуль – языковая конструкция, объединяющая взаимосвязанные ресурсы в именованныйнабор, позволяющая использовать эти ресурсы, изменять и транслировать их.Фортран, А-60, Стандартный Паскаль: в них были физические модули.ТД = множество операций + множество значений.
Одна из основных целей ЛМ – определение новых типовданных. Класс в современных ООП является логическим модулем, а вот структура как таковая не является.Объединение, например, математических функций в один модуль логично и помогает программисту (Math,там только статические члены-функции).II) ЛМ в языках М-2, Оберон, DelphiМ-2: вообще говоря, весь проект разбивается на модули:• главный модуль (в нем, собственно, программа)MODULE name; var …; BEGIN operators … END name.•библиотечные модули (БМ)o модуль определенийDEFINITION MODULE M; var …; END M;o•Объекты данныхТипы данныхЗаголовки процедур и функциймодуль реализацийIMPLEMENTATION MODULE M; var …, realization…; END M;логические модули (пример: мониторы, не будем их разбирать)Пример реализации модуля объявлений (интерфейс) стека на М-2:DEFINITION MODILE Stacks;CONST N = 256;TYPE StackRECORDTOP: INTEGER;BODY: ARRAY [0..N] of REAL;END;PROCEDURE INIT(VAR S: Stack);PROCEDURE POP(VAR S: Stack): REAL;… … …VAR Done: BOOLEAN; //для контроля успешности выполненияEND Stacks;Модуль определений + Модуль реализации => UNIT:Delphi:unit Stackinterface…implementation…end Stacks.//модуль интерфейса//модуль реализацииРассмотрим взаимодействие модулей между собой.
БМ что-то экспортирует и импортирует из модулейреализации. Очень важно понятие видимости: потенциальная видимость и непосредственная видимость(т.е. имя может использоваться без всяких уточнений).Уточненный идентификатор имеет такую форму:имя_модуля.идентификаторМ_1М_2…M_NDEFINITION_1DEFINITION_2…DEFINITION_NIMPLEMENTATION_1IMPLEMENTATION_2…IMPLEMENTATION_NИмпорт, нужен для того, чтобы имена стали непосредственно видимыми:IMPORT список_имен_БМ;VAR S: Stacks.Stack;FROM Stacks IMPORT Stack, Pop, Push;Если не импортировать, то непосредственно видимыми в М-2 являются только стандартныеидентификаторы и имена модулей. В языке Си есть проблема с пространством имен – оно одно.В языке Оберон все еще проще.
Нет главного модуля. Экспортируемые процедуры без параметровназываются командами (М.Р, есть команда загрузки – LOAD M). Т.е. есть только библиотечные модули,которые бывают модулями определений и просто модулями (реализации).
В языке Оберон-2 вообщеостался только один модуль т.к. модуль определений в принципе может быть сгенерирован из модуляреализации (в нем нужно как-то помечать экспортируемые имена, например звездочкой). Существуютспециальные утилиты для такой генерации. Все глобальные имена здесь тоже видны только с уточнением.III) Логические модули в языке Адаpackage имя isобъявления;end имя;package body имя isопределения всех процедур и функций;end имя;//определения пакета//тело пакетаПакеты в Ада могут быть вложенными. Это и есть главное отличие от М-2, которое все усложняет.
Естьглобальный пакет STANDARD, в который вложены все пакеты проекта. Вложенность тел пакетов должнабыть такая же, как вложенность объявлений пакетов. Соответственно определяется и область видимостиимен (переменных и пакетов). Непосредственно в «своем» пакете имя видимо непосредственно, а всеобъявленные ранее имена видны через уточнение. Появляется дерево видимости.[lect21]Также могут быть чисто служебные пакеты, которые нужны только для реализации.package P ispackage P1 isPackage P2 is.....end P2endP1...package body P ispackage body P1 ispackage body P2 ispackage AUX is....end AUXpackage body AUX is....end AUXend P1end PПакет AUX виден только внутри пакета P2 и не может использоваться больше нигде.Top-Down подход к программированию - сначала главный модуль, спецификация, проектирование и т.д.Такой подход очень красив и позволяет, начиная с самых главных проблем переходить к более мелким.Недостатки такой системы: главный модуль начинает работать только тогда, когда написаны самые нижниемодули, а это как правило ввод-вывод.