Чтение онлайн

на главную - закладки

Жанры

Чистая архитектура. Искусство разработки программного обеспечения
Шрифт:

Этот прием широко применялся [15] программистами до появления ОО. Фактически именно так C++ реализует единственное наследование.

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

15

И продолжает применяться.

Обратите также внимание, как в

main.c
мне пришлось приводить аргументы
NamedPoint
к типу
Point
. В настоящем языке ОО такое приведение к родительскому типу производится неявно.

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

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

Но у нас есть еще одно понятие.

Полиморфизм?

Была ли возможность реализовать полиморфное поведение до появления языков ОО? Конечно! Взгляните на следующую простую программу copy на языке C.

#include <stdio.h>

void copy {

 int c;

 while ((c=getchar)!= EOF)

 putchar(c);

}

Функция

getchar
читает символы из
STDIN
. Но какое устройство в действительности скрыто за ширмой
STDIN
? Функция
putchar
записывает символы в устройство
STDOUT
. Но что это за устройство? Эти функции являются полиморфными – их поведение зависит от типов устройств
STDIN
и
STDOUT
.

В некотором смысле

STDIN
и
STDOUT
похожи на интерфейсы в силе Java, когда для каждого устройства имеется своя реализация этих интерфейсов. Конечно, в примере программы на C нет никаких интерфейсов, но как тогда вызов
getchar
передается драйверу устройства, который фактически читает символ?

Ответ на этот вопрос прост: операционная система UNIX требует, чтобы каждый драйвер устройства ввода/вывода реализовал пять стандартных функций [16] :

open
,
close
,
read
,
write
и
seek
. Сигнатуры этих функций должны совпадать для всех драйверов.

16

В разных версиях UNIX требования разные; это всего лишь пример.

Структура FILE имеет пять указателей на функции. В нашем случае она могла бы выглядеть как-то так:

struct FILE {

 void (*open)(char* name, int mode);

 void (*close);

 int (*read);

 void (*write)(char);

 void (*seek)(long index, int mode);

};

Драйвер консоли определяет эти функции и инициализирует указатели на них в структуре FILE примерно так:

#include "file.h"

void open(char* name, int mode) {/*…*/}

void close {/*…*/};

int read {int c;/*…*/ return c;}

void write(char c) {/*…*/}

void seek(long index, int mode) {/*…*/}

struct FILE console = {open, close, read, write, seek};

Если

теперь предположить, что символ
STDIN
определен как указатель
FILE*
и ссылается на структуру console, тогда
getchar
можно реализовать как-то так:

extern struct FILE* STDIN;

int getchar {

 return STDIN->read;

}

Иными словами,

getchar
просто вызывает функцию, на которую ссылается указатель read в структуре
FILE
, на которую, в свою очередь, ссылается
STDIN
.

Этот простой трюк составляет основу полиморфизма в ОО. В C++, например, каждая виртуальная функция в классе представлена указателем в таблице виртуальных методов

vtable
и все вызовы виртуальных функций выполняются через эту таблицу. Конструкторы производных классов просто инициализируют таблицу
vtable
объекта указателями на свои версии функций.

Суть полиморфизма заключается в применении указателей на функции. Программисты использовали указатели на функции для достижения полиморфного поведения еще со времен появления архитектуры фон Неймана в конце 1940-х годов. Иными словами, парадигма ОО не принесла ничего нового.

Впрочем, это не совсем верно. Пусть полиморфизм появился раньше языков ОО, но они сделали его намного надежнее и удобнее.

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

Языки ОО избавляют от необходимости помнить об этих соглашениях и, соответственно, устраняют опасности, связанные с этим. Поддержка полиморфизма на уровне языка делает его использование тривиально простым. Это обстоятельство открывает новые возможности, о которых программисты на C могли только мечтать. Отсюда можно заключить, что ОО накладывает ограничение на косвенную передачу управления.

Сильные стороны полиморфизма

Какими положительными чертами обладает полиморфизм? Чтобы в полной мере оценить их, рассмотрим пример программы

copy
. Что случится с программой, если создать новое устройство ввода/вывода? Допустим, мы решили использовать программу
copy
для копирования данных из устройства распознавания рукописного текста в устройство синтеза речи: что нужно изменить в программе copy, чтобы она смогла работать с новыми устройствами?

Самое интересное, что никаких изменений не требуется! В действительности нам не придется даже перекомпилировать программу

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

Проще говоря, устройства ввода/вывода превратились в плагины для программы

copy
.

Поделиться:
Популярные книги

Звезда сомнительного счастья

Шах Ольга
Фантастика:
фэнтези
6.00
рейтинг книги
Звезда сомнительного счастья

Царевна Софья

Карнович Евгений Петрович
Всемирная история в романах
Проза:
историческая проза
6.25
рейтинг книги
Царевна Софья

Имперец. Земли Итреи

Игнатов Михаил Павлович
11. Путь
Фантастика:
героическая фантастика
боевая фантастика
5.25
рейтинг книги
Имперец. Земли Итреи

Если твой босс... монстр!

Райская Ольга
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Если твой босс... монстр!

Измена. Верни мне мою жизнь

Томченко Анна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Верни мне мою жизнь

Законы Рода. Том 10

Андрей Мельник
10. Граф Берестьев
Фантастика:
юмористическая фантастика
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 10

Держать удар

Иванов Дмитрий
11. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Держать удар

Идеальный мир для Лекаря 4

Сапфир Олег
4. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 4

На границе империй. Том 3

INDIGO
3. Фортуна дама переменчивая
Фантастика:
космическая фантастика
5.63
рейтинг книги
На границе империй. Том 3

Честное пионерское! Часть 1

Федин Андрей Анатольевич
1. Честное пионерское!
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Честное пионерское! Часть 1

Призыватель нулевого ранга

Дубов Дмитрий
1. Эпоха Гардара
Фантастика:
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Призыватель нулевого ранга

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

70 Рублей - 2. Здравствуй S-T-I-K-S

Кожевников Павел
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
постапокалипсис
5.00
рейтинг книги
70 Рублей - 2. Здравствуй S-T-I-K-S

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая