Главная » Просмотр файлов » М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)

М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781), страница 40

Файл №1160781 М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)) 40 страницаМ. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781) страница 402019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

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

• инкапсуляции и абстракции данных,

• наследования,

• динамического полиморфизма.

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

Такие модули, как пакеты в языке Ada, инкапсулируют вычислительные ресурсы, выставляя только спецификацию интерфейса. Абстракция данных может быть достигнута через определение представления данных в закрытой части, к которой нельзя обращаться из других единиц. Единица инкапсуля­ции и абстракции в языке C++ — это класс (class), который содержит объявления подпрограмм и типов данных. Из класса создаются фактические объек­ты, называемые экземлярами(instances). Пример класса в языке C++:

class Airplane_Data {

public:

char *get_id(char *s) const {return id;}

void set_id(char *s) {strcpy(id, s);}

int get_speed() const {return speed;}

void set_speed(int i) {speed=i;}

int get_altitude() const {return altitude;}

void set_altitude(int i) {altitude = i;}

private:

char id[80];

int speed;

int altitude;

};

Этот пример расширяет пример из предыдущей главы, создавая отдельный класс для данных о каждом самолете. Этот класс может теперь использоваться другим классом, например тем, который определяет структуру для хранения данных о многих самолетах:

class Airplanes {

public:

void New_Airplane(Airplane_Data, int &);

void Get_Airplane(int, Airplane_Data &) const;

private:

Airplane_Data database[100];

int current_airplanes;

int find_empty_entry();

};

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

Вы можете задать вопрос, почему Airplane_Data лучше сделать отдельным классом, а не просто объявить обычной общей (public) записью. Это спорное проектное решение: данные должны быть скрыты в классе, если вы полагае­те, что внутреннее представление может измениться. Например, вы можете знать, что один заказчик предпочитает измерять высоту в английских футах, тогда как другой предпочитает метры. Определяя отдельный класс для

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

За эту гибкость приходится платить определенную цену; каждый доступ к значению данных требует вызова подпрограммы:

Aircraft_Data a; // Экземпляр класса

int alt;

alt = a.get_altitud(e); // Получить значение, скрытое в экземпляре

alt = (alt* 2)+ 1000;

a.set_altitude(alt); // Вернуть значение в экземпляр

вместо простого оператора присваивания в случае, когда а общая (public) за­пись:

a.alt = (a.alt*2) + 1000;

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

Однако инкапсуляция вовсе не обязана сопровождаться значительными затратами времени выполнения. Как показано в примере, тело интерфейс­ной функции может быть написано внутри объявления класса; в этом случае функция является подставляемой (встраиваемой, inline) функцией, т.е. не ис­пользуется механизм вызова подпрограммы и возврата из нее (см. гл. 7). Вместо этого код тела подпрограммы вставляется непосредственно внутрь последовательности кода в точке вызова. Поскольку при подстановке функции мы расплачиваемся пространством за время, подпрограммы должны быть очень маленькими (не более двух или трех команд). Другой фактор, который следует рассмотреть перед подстановкой подпрограммы, это то, что она вводит дополнительные условия для компиляции. Если вы изменяете подставляемую подпрограмму, все клиенты должна быть пере­компилированы.

14.3. Наследование

В разделе 4.6 мы показали, как в языке Ada один тип может быть получен из другого так, что производный тип получает копии значений и операций, которые были определены для порождающего типа. Задав порождающий тип:

package Airplane_Package is

type Airplane_Data is

record

Ada

ID:String(1..80);

Speed: Integer range 0.. 1000;

Altitude: Integer range 0..100;

end record;

procedure New_Airplane(Data: in Airplane_Data: I; out Integer);

procedure Get_Airplane(l: in Integer; Data: out Airplane_Data);

end Airplane_Package;

производный тип можно объявить в другом пакете:

Ada


type New_Airplane_Data is

new Airplane_Package.Airplane_Data;

Можно объявлять новые подпрограммы, которые выполняют операции на производном типе, и заменять подпрограммы родительского типа новыми:

procedure Display_Airplane(Data: in New_Airplane_Data);

Ada

-- Дополнительная подпрограмма

procedure Get_Airplane(Data: in New_Airplane_Data; I: out Integer);

-- Замененная подпрограмма

-- Подпрограмма New_Airplane скопирована из Airplane_Data

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

Ada

А1: Airplane_Data;

А2: New_Airplane_Data := New_Airplane_Data(A1);

A3: Airplane_Data := Airplane_Data(A2);

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

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

В таком случае лучше использовать наследование (inheritance), которое яв­ляется способом расширения существующего типа, не только путем добавле­ния и изменения операции, но и добавления данных к типу. В языке C++ это реализовано через порождение одного класса из другого:

class SST_Data: public Airplane_Data {

private:

float mach;

C++

public:

float get_mach() const {return mach;};

void set_mach(float m) {mach = m;};

};

Производный класс SST_Data получен из существующего класса Airplane_Data. Это означает, что каждый элемент данных и каждая подпро­грамма, которые определены для базового класса (base class), доступны и в производном классе. Кроме того, каждое значение производного класса SST_Data будет иметь дополнительный компонент данных mach, и есть две новые подпрограммы, которые могут применяться к значениям производно­го типа.

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

C++

SST_Data s;

s.set_speed(1400); //Унаследованная подпрограмма

s.set_mach(2.4); // Новая подпрограмма

Подпрограмма, вызванная для set_mach, — это подпрограмма, которая объ­явлена внутри класса SST_ Data, а подпрограмма, вызванная для set_speed, — это подпрограмма, которая унаследована от базового класса. Обратите внима­ние, что производный класс может быть откомпилирован и скомпонован без изменения и перекомпиляции базового класса; таким образом, расширение на существующий код воздействовать не должно.

14.4. Динамический полиморфизм в языке C++

Когда один класс порожден из другого класса, вы можете замещать (override) унаследованные подпрограммы в производном классе, переопределяя их:

class SST_Data: public Airplane_Data {

public:

int get_spaed() const; // Заместить

void set_speed(int): // Заместить

};

Если задан вызов:

obj.set_speed(100);

то решение, какую именно из подпрограмм вызвать — подпрограмму, унасле­дованную из Airplane_Data, или новую в SST_ Data, — принимается во время компиляции на основе класса объекта оbj.Это называется статическим связы­ванием (static binding), или ранним связыванием (early binding), так как решение принимается до выполнения программы, и при выполнении всегда вызывает­ся одна и та же подпрограмма.

Однако вся суть наследования состоит в том, чтобы создать группу классов с аналогичными свойствами, и резонно ожидать, что должна иметься возмож­ность присвоить переменной значение, принадлежащее любому из этих клас­сов. Что должно произойти, когда вызывается подпрограмма для такой переменной? Решение, какую подпрограмму вызывать, должно быть принято во время выполнения, потому что значение, содержащееся в переменной, до этого неизвестно; фактически, переменная может содержать значения разных классов в разное время выполнения программы. Термины, используемые для обозначения способности выбирать подпрограммы во время выполнения, — динамический полиморфизм, динамическое связывание, позднее связывание и дис­петчеризация во время выполнения (dynamic polymorphism, dynamic binding, late binding и run-time dispatching).

В языке C++ используются виртуальные функции (virtual functions) для обозначения тех подпрограмм, для которых выполняется динамическое свя­зывание:

class Airplane_Data {

private:

public:

virtual int get_speed() const;

virtual void set_speed(int);

….

};

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

class SST_Data : public Airplane_Data {

private:

float mach;

public:

float get_mach() const; // Новая подпрограмма

void set_mach(float m); // Новая подпрограмма

virtual int get_speed() const; // Заместить виртуальную подпрограмму

virtual void set_speed(int); // Заместить виртуальную подпрограмму

};

Рассмотрим теперь процедуру update со ссылочным параметром на базо­вый класс:

void update(Airplane_Data & d, int spd, int alt)

}

d.set_speed(spd); // На какой тип указывает d??

d.set altitude(alt); //На какой тип указывает d??

}

Airplane_Data a;

SST_Data s;

void proc()

{

update(a, 500, 5000); // Вызвать с AirplaneJData

update(s, 800,6000); // Вызвать с SST_Data

}

Идея производных классов состоит в том, что производное значение является базовым значением (возможно, с дополнительными полями), поэтому update может вызываться с параметром s производного класса SST_Data. При компиляции update компилятор не может знать, на что указывает d: на значе­ние Airplane_Data или на SST_Data. Поэтому он не может однозначно скомпи­лировать вызов set_speed, поскольку эта подпрограмма по-разному определена в двух классах. Следовательно, компилятор должен сгенерировать код для переключения (диспетчеризации) вызова на правильную подпрограм­му во время выполнения в зависимости от того, на что указывает d. В первом вызове ргос указатель d указывает на Airplane_Data, и вызов будет диспет-черизован на подпрограмму, определенную в классе Airplane_Data, тогда как второй — на подпрограмму, определенную в SST_ Data.

Позвольте нам подчеркнуть преимущества динамического полиморфизма: вы можете писать большие блоки программы полностью в общем виде, ис­пользуя вызовы виртуальных подпрограмм. Специализация обработки конк­ретного класса в семействе производных классов делается только во время выполнения за счет диспетчеризации виртуальных подпрограмм. Кроме тогo если вам когда-либо понадобится добавить производные классы в семействе не нужно будет изменять или перекомпилировать ни один из существующиx кодов, потому что любое изменение в существующей программе ограниченo исключительно новыми реализациями виртуальных подпрограмм. Например если мы порождаем еще один класс:

class Space_Plane_Data : public SST_Data {

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

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

Список файлов книги

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