Лекция 9 (Лекции (2009) (Саша Федорова))

2019-09-19СтудИзба

Описание файла

Файл "Лекция 9" внутри архива находится в папке "Лекции (2009) (Саша Федорова)". Документ из архива "Лекции (2009) (Саша Федорова)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "Лекция 9"

Текст из документа "Лекция 9"

6


Лекция 9.

Пункт 4.1 Подпрограммный тип данных

(зачем он нужен и везде ли есть)

Из рассматриваемых нами языков программирования подпрограммный тип данных есть не везде. То есть почти везде, кроме Java и Ada 1983.

Какие есть аргументы за и против включения функционального типа данных в язык программирования?

Каковы технологические потребности?

  1. Передача подпрограмм как параметров.

В Pascal введено 2 вида подпрограмм как формальных параметров: процедуры и функции. Аналогичный подход можно заметить и в других языках.

В Си подпрограммный тип данных усложнен понятием указателя.

Можно рассматривать подпрограммный тип данных как множество констант, тогда единственными операциями для подпрограммного типа данных будут

  1. присваивание (передача параметров по значениям)

  2. вызов

Типичный пример Integral. У него в качестве параметров существует процедурный тип – f(подынтегральная функция).

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

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

С++, Modula-2, Оберон

void f(int) – это прототип функции, объявление некоторой функциональной константы. Если перед ней поставить typedef, что имя функции станет синонимом нового типа:

typedef void f(); //f стал синонимом нового типа

Можно (и даже часто нужно) делать так:

typedef void (*f)(int)

(А лучше все делать через typedef )

Пример определения функции через typedef:

type Func_Pointer is access function(L, e: Float) return Boolean

function Comparenum(X, Y: Float) return Boolean is

…..

end Comparenum

Теперь если есть

F: FuncPointer

F:=Comparenum;

Указатели служат в Аде-83 только для указателей на обьекты динамической памяти.

А в Аде - 95 введен был специальный указательный тип, который могли

ссылаться на любые обьекты.

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

Пример:

Oberon, Modula-2

TYPE FUNC_INT = PROCEDURE (L, R: REAL): BOOLEAN

И пусть есть процедура COMPARE

PROCEDURE COMPARE(X, Y: REAL): BOOLEAN;

VAR F: FUNC_INT;

Тогда можно сказать так:

F:=COMPARE;

F(0, A); //вызов соответсвующей функции

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

Классический пример – таймер. Есть некий обьект «таймер», в нем помещается указатель на функцию обратного вызова, которая вызывается при наступлении данного события (по истечении времени таймера, например).

В Ада-83 родовые сегменты также связаны с функциями обратного вызова.

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

Пример. X Windows System - система графики в Unix.

Идеи объектно-ориентированных языков все больше проникали в массы, механизм наследования все чаще реализовывался через функции обратного вызова.

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

Оберон-2 – появилось динамическое связывание методов.

Замечание

В Аде динамическое связывание методов появилось не сразу. Если взять чисто объектно-ориентированный язык, то в нем любой обьект данных принадлежит некоторому классу (из соображений эффективности). В таких объектно-ориентированных языках, как Java, существуют простые типы данных и классы, а также классы-автоупаковки(in-boxing) и автораспаковки, позволяющие любой простой тип данных сопоставить некоторому обьекту. В Java, заметим, так и не появилось процедурного типа данных: все подобные вещи в чисто объектно-ориентированных языках пишутся через интерфейсы. (Такой же подход и в C#: класс, только класс, и нечего кроме класса нам не надо )

Интересно, что в С# существует 2 способа реакции на события (в классических языках программирования существует только один способ реакции на событие). Пример- OnClick()//работает механизм наследования и замещения.

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

В С# понятие объектно-ориентированного вызова осталось: делегат – интересное расширение понятия подпрограммного типа.

Прежде чем рассматривать подробности Delegat в C#, рассмотрим, какие встречаются подходы к реализации данной особенности языка.

В Turbo Pascal (а точнее, в Delphi) существовал классический подпрограммный тип данных.

type PRC=procedure(var i:integer) of T;

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

type T = class

………………………..

procedure FOO(var j:integer);

end

В чем отличие методов класса от глобальных функций? Они не могут существовать без объекта. У метода есть скрытый параметр this(указатель на обьект класса, который вызывает данный метод). Вызов метода может существовать только в контексте объекта:

Обьект t класса Т:

t.f();

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

В языке С++ введено понятие указателя на член класса.

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

Пример.

typedef void (*f)(int);

void g(int)

Параллельно с этим Стауструп ввел понятие указателя на член класса:

void f(int)

{

int i;

}

F F_ptr;

F_ptr=g;//может, я не так поняла и здесь стоял &.

Каким будет описание указателя на функцию-член класса? Любой указатель, стало быть, станет ::Х. То есть:

(X:: *)int p;

В C++ указатель на член класса – это смещение его относительно начала объекта (по сути, это не указатель даже). Указатель на член данных – то также смещение относительно начала объекта класса X.

сlass X{

int j;

void f(int);

int i;

}

Согласно подходу Страуструпа, мы «предоставляем» this и информацию, находящуюся в этом указателе (смещения всех обьектов).

Что происходит в случае, если метод класса – статический?

static void p(int);

Тогда можно написать

F ptr = X::p;

Вернемся к понятию делегата в C#. Делегаты в С# используются для функций обратного вызова(Пусть есть некоторый обьект. Иногда в нем происходит что-то интересное. Другие обьекты могут как-то реагировать на это. Как только это «что-то» происходит, вызывается callback. При вызове важно не забыть о том, что функция обратного вызова – это указатель:

if(callback)

callback(0);

)

Идея: если бы мы имели дело с С++ или с Delphi, то надо было бы работать с указателем. Если несколько обьектов «хотят реагировать» на соответствующие вещи, нужно делать контейнеры из соответствующих вызовов.

В С# функция обратного вызова – это не функция, а делегат.(delegate, в System – Multicast + Delegate)

Пример объявления делегата в C#:

public delegate прототип функции

public delegate void f(int);

f в данном случае становится именем делегата. Это не есть прототип функции. Фактически f ведет себя как имя типа, к которому относятся все функции с соответствующей сигнатурой.

class X{

public delegate void delf(int);

delf g; //g – это переменная делегатного типа, так называемая цепочка функций.

}

Операции делегата:

  • присваивание (инициализация)(=)

  • добавление делегата(+=)

  • «убирание» делегата(-=)

  • Вызов (скобочки: ())

В любой из этих операций делегат – это цепочка указателей на функцию.

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

class X{

void fy(int);

}

class Y{

void fy(int)

}

сlass G{

void h(int);

}

void delf(int)

X a=new X();

Y b= new Y();

G c = new G();

a.g=a.f;//не совсем верно, лучше: a.g = new delf(a.f);

a.g+=b.fy;//описана в классе Y

a.g+=G.h

}

Таким образом, операции += и -= позволяет соответственно добавить или убрать делегат.

Таким образом, делегат в С# - заменитель процедурного типа данных.

Механизм подписка-рассылка

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

Пусть у нас есть объект

Event Producer; //порождает события

И объект

EventConsumer;//«потребитель» события

В общем случае может быть много Producer-ов и Consumer-ов.

Пример.(Почта)

EventProducer делает:

public delegate void GhNewMail(object o);

OnNewMail onNewMail;

Вызов пустого делегата допустим (он ничего не делает).

EventProducer ep = new EventProducer;

EventConsumer ec = new EventConsumer;

EventConsumer ec1 = new EventConsumer;

ec.OnNewMail+=new OnNewMail(ec1); //подписка NewMailMessage. – обьект «подписался» на сообщения от другого объекта

При этом у класса EventConsumer должна быть описана функция void NewMail()

Внутри EventProducer:

public NewMail(Mail Message); //рассылка

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

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

*конец функциональных типов данных*

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