
Полиморфизм методов
Четвертая, и последняя, из базовых концепций ООП — полиморфизм. Его суть заключается в том, что родственные методы, реализованные на разных уровнях иерархии, могут иметь одинаковые имена. Это упрощает их запоминание.
Принадлежность метода к тому или иному объекту определяется на основании его аргументов. Например, вместо двух методов — PlayVideo() и PlayMIDI() — можно создать один метод Р1ау(), которому в первом случае передается видео клип, а во втором случае — MIDI файл.
Поскольку компоновщик не может определить, к какому объекту относится "двусмысленный" метод, это должен сделать компилятор. В процессе уточнения имен компилятор разрешает все неоднозначности, вставляя перед именем метода имя его объекта.
Характеристики объектов
С объектами связан целый ряд терминов и определений. Важно понимать их назначение, чтобы правильно употреблять.
Классы и объекты
Программисты часто путаются в терминах "класс" и "объект". Класс — это описание категории родственных объектов, а объект — это конкретный экземп ляр класса. Класс можно сравнить с чертежом, а объект — с домом, построенным на основании этого чертежа.
Читателям наверняка известен тип данных struct языка С, описывающий структуру, которая состоит из набора полей. Класс — это разновидность структу ры, в которую кроме переменных могут также входить и функции. Создать объ ект класса — это то же самое, что создать переменную, в качестве типа которой указан тэг структуры.
Замечание
До сего момента термин объект означал как класс, так и собственно объект. Это было сделано умышленно, чтобы уменьшить путаницу. ,
Виерархии наследования есть два типа классов: надкласс (родительский класс)
иподкласс (производный, или дочерний, класс). Надкласс, находящийся на са мом верхнем уровне иерархии, называется суперклассом и обычно является абст
рактным. Любой класс, наследующий свое поведение от некоторого родитель ского класса, называется подклассом.
Атрибуты
Отдельные поля структуры становятся атрибутами в классе. Атрибуты могут быть как скрытыми (инкапсулированными), так и опубликованными (являющимися частью открытого интерфейса класса). Как правило, все атрибуты класса скрыты от внешнего мира.
Глава 11. Экономия времени за счет объектов |
241 |
Ⱦɚɧɧɚɹ ɜɟɪɫɢɹ ɤɧɢɝɢ ɜɵɩɭɳɟɧɚ ɷɥɟɤɬɪɨɧɧɵɦ ɢɡɞɚɬɟɥɶɫɬɜɨɦ %RRNV VKRS Ɋɚɫɩɪɨɫɬɪɚɧɟɧɢɟ ɩɪɨɞɚɠɚ ɩɟɪɟɡɚɩɢɫɶ ɞɚɧɧɨɣ ɤɧɢɝɢ ɢɥɢ ɟɟ ɱɚɫɬɟɣ ɁȺɉɊȿɓȿɇɕ Ɉ ɜɫɟɯ ɧɚɪɭɲɟɧɢɹɯ ɩɪɨɫɶɛɚ ɫɨɨɛɳɚɬɶ ɩɨ ɚɞɪɟɫɭ piracy@books-shop.com
Свойства
Опубликованные атрибуты класса называются свойствами. Обычно они дос тупны только для чтения или же представлены в виде связки функций Getxxx() и Setxxx(), позволяющих получать и задавать их значения.
Семейства Get() и Set()
Функции семейств Get() и Set О не считаются методами. Они относятся к особому набору функций, предназначенных исключительно для извлечения и установки свойств объектов, и не расширяют их функциональные возможности.
Подклассы наследуют свойства своих родительских классов.
Методы
Методы — это действия, которые выполняет объект. Благодаря полиморфизму дочерние классы могут переопределять методы, унаследованные от своих роди тельских классов. Обычно при этом вызывается исходный метод, чтобы роди тельский класс мог проинициализировать свои закрытые атрибуты.
Атрибуты, свойства и методы называются членами класса.
Права доступа
Права доступа определяют, кто может обращаться к той или иной части клас са. В Java и C++ определены три уровня доступа: private, protected и public.
•private. Доступ к членам класса разрешен только из его собственных методов.
•protected. Доступ к членам класса разрешен из его методов, а также из методов его подклассов.
•public. Доступ к членам класса разрешен отовсюду.
Эти ограничения можно ослаблять, создавая дружественные классы и функ ции.
Отношения
Объекты взаимодействуют друг с другом тремя различными способами. Пер вый — наследование — был описан выше. Все три способа идентифицируются ключевыми фразами: является, содержит, использует. На этапах анализа и проек тирования эти отношения помечаются специальными значками.
•Отношение "является". Наследование: один класс наследует свойства и методы другого.
•Отношение "содержит". Включение: один класс является членом дру гого.
•Отношение "использует". Использование: один класс объявлен дружест венным другому или же вызывает его открытые методы.
242 |
Часть III. Объектно ориентированные сокеты |
www.books-shop.com
Между двумя объектами должно существовать только одно отношение. На пример, объект А не может быть потомком объекта Б и в то же время содержать его в качестве встроенного объекта. Подобная двойственность отношений свиде тельствует о неправильно выполненном анализе.
Расширение объектов
Когда есть хороший объект, всегда хочется его расширить или еще улучшить. Помните о том, что перечисленные ниже способы расширения поддерживаются не во всех языках.
Шаблоны
Благодаря абстракции и полиморфизму можно создавать в родительских клас сах обобщенные методы, конкретная реализация которых предоставляется в до черних классах. А теперь представьте, что существуют обобщенные классы, эк земплярами которых являются конкретные классы. В C++ такие классы называ ются шаблонами. В них дано описание методов, не зависящее от конкретного типа данных.
При создании конкретного экземпляра шаблона указывается, с данными ка кого типа будет работать этот класс. Обычно на базе шаблонов создаются кон тейнеры объектов. Например, очередь и стек работают независимо от того, дан ные какого типа в них находятся.
Постоянство
Обычно программисты имеют дело с объектами, которые прекращают свое существование по завершении программы. Но в некоторых программах пользова телю разрешается задавать параметры, влияющие на работу объектов. Эти пара метры должны оставаться в силе при последующих запусках программы.
Такого рода информация сохраняется в файле. Когда программа запускается на выполнение, она загружает свои параметры из файла и продолжает работу с того момента, с которого ее прекратила. Можно даже сделать так, что в случае системного сбоя программа незаметно для пользователя восстановит разорванное соединение.
Потоковая передача данных
Представьте, что объект пакует сам себя и записывает на диск либо посылает куда то по сети. По достижении места назначения или же когда программа за гружает объект, он автоматически распаковывает себя. Подобная методика ис пользуется при обеспечении постоянства объектов и в распределенном програм мировании. В частности, она реализована в Java. Элементы потоковой обработки можно применять и в C++, но самоидентификация объектов (называемая ин! троспективным анализом в Java) здесь невозможна.
Глава 11. Экономия времени за счет объектов |
243 |
www.books-shop.com
Перегрузка
Перегрузка операторов (поддерживаемая в C++) расширяет концепцию поли морфизма, Некоторые программисты ошибочно полагают, что это тождественные понятия, но на самом деле перегрузка операторов является объектным расшире нием C++. В Java, например, она не поддерживается, хотя этот язык считается объектно ориентированным.
В C++ разрешается добавлять новый (не переопределять старый!) смысл к внутренним операторам языка. С ними можно обращаться как с полиморфными методами класса, создавая дополнительные реализации, которые работают с но выми типами данных. Перегрузка операторов подвержена целому ряду ограниче ний.
•Расширение, а не переопределение. Нельзя создавать операторы, чьи опе ранды относятся к тому же типу, что и раньше; например, нельзя поме нять смысл операции (int)+(int).
•Не все операторы доступны. Переопределять можно практически все операторы, за исключением нескольких (например, условный оператор ?:).
•Число параметров должно совпадать. Новый оператор должен иметь то же число операндов, что и его исходная версия, т.е. он должен быть ли бо унарным (один операнд), либо бинарным (два операнда).
Нельзя также изменить приоритет оператора и его ассоциативность (порядок вычисления операндов).
Интерфейсы
ВC++ существует одна проблема. Если класс А использует класс Б, структура последнего должна быть непосредственно известна программисту или же одним из предков класса Б должен быть класс, являющийся потомком для А. Когда класс Б поддерживает несколько интерфейсов, возникают неприятности с множе ственным наследованием.
ВJava можно просто объявить, что класс поддерживает конкретный абстракт ный интерфейс. Это не налагает на сам класс никаких ограничений или дополни тельных обязательств и не добавляет к нему лишнего кода.
События и исключения
Последнее расширение связано с восстановлением работоспособности про граммы в случае ошибок. В языке С это постоянная проблема, так как обработка ошибок, как правило, ведется не там, где они возникают.
С помощью исключений можно задать, когда и как следует обрабатывать кон кретные виды ошибок, возникающих в объектах, причем обработчик исключений является членом того же класса, что и объект, в котором возникла ошибка. Со бытия — это ситуации, возникающие асинхронно и вызывающие изменение хода выполнения программы. Обычно они применяются в интерактивных программах, которые либо дожидаются наступления нужного события, чтобы начать выпол няться, либо выполняются, пока не наступит требуемое событие.
244 |
Часть III. Объектно ориентированные сокеты |
www.books-shop.com
Особые случаи
Объектная технология сталкивается с теми же проблемами, что и другие тех нологии программирования. Не все задачи можно сформулировать в терминах ООП. Ниже мы рассмотрим особые виды классов и попытаемся разобраться, как с ними работать.
Записи и структуры
Правило гласит, что класс без методов является записью. Часто именно записи служат основным средством представления данных. Например, в базах данных информация хранится в виде записей.
Запись, или структура, — это неупорядоченный набор данных. Единственные методы, присутствующие в нем, — это функции вида Get() и Set(). Объекты по добного рода встречаются редко. Необходимость их существования проверяется следующими вопросами.
•Существует ли тесная связь между полями записи? Например, может ока заться, что при модификации одного поля должно измениться другое. Следует выявить связанные таким способом поля и запрограммировать их изменения в функциях Set().
•Является ли объект частью более крупной системы? В базах данных на многие отношения, существующие между таблицами, наложены ограни чения в виде деловых правил, обеспечивающих целостность данных. Ес ли видеть только одну сторону отношения, то может казаться, что ника ких функций не требуется. На самом деле функции связаны со всем от ношением в целом.
Наборы функций
Набор функций противоположен записи, т.е. набору данных. Это класс, в ко тором присутствуют только методы, но нет никаких атрибутов и свойств. В каче стве примера можно привести библиотеку математических функций. Такие функ ции выполняются над числами типа int и float, но они не связаны с ними и не формируют с ними единый класс.
Если в результате проектирования у вас получился класс, представляющий со бой набор функций, проверьте его правильность следующими вопросами.
•Правильно ли распределены обязанности объектов? Возможно, процесс проектирования зашел дальше, чем нужно, в результате чего нарушилась атомарность объектов — были созданы два объекта вместо одного. Не исключено, что некоторые из них следует объединить.
•Существует ли тесная взаимосвязь между классами? Когда один класс активно вызывает методы другого класса, то, возможно, некоторые из
них просто принадлежат неправильному классу.
• Связаны ли между собой методы ? Любой метод должен явно или неявно влиять на выполнение других методов класса. Если этого не происходит, значит, методы не связаны друг с другом.
Глава 11. Экономия времени за счет объектов |
245 |
www.books-shop.com
Языковая поддержка
Поддержка объектов внедрена во многие современные языки программиро вания. Существует даже объектная версия Cobol. Классическими объектно ориентированными языками являются SmallTalk и Eiffel. Объектно ориенти рованными можно считать также языки Java и C++, знакомству с которыми будут посвящены две последующие главы. В то же время поддержка объектов во всех этих языках реализована настолько по разному, что необходимо провести их классификацию.
Классификация объектно ориентированных
языков
В действительности лишь некоторые языки являются истинно объектно ориентированными. Среди распространенных языков к таковым можно отнести, пожалуй, лишь SmallTalk. Любые действия, выполняемые в этом языке, рассмат риваются как действия над объектами.
По отношению к таким языкам, как C++ и Java, можно сказать, что они пред! назначены для работы с объектами. В них поддерживаются практически все кон цепции ООП, и на этих языках пишутся очень эффективные объектно ориентированные программы. Но ничто не мешает вам, к примеру, в среде C++ написать и скомпилировать обычную С программу. В ней даже можно создать квазиобъекты с помощью типа данных struct. Даже Java программа может пред ставлять собой одну большую функцию main(). Особенностью таких языков явля ется то, что они не заставляют программиста придерживаться всех принципов объектной технологии.
Наиболее слабой формой объектной ориентации является поддержка. В таких языках элементы объектной технологии служат дополнением к базовым возмож ностям языка, и применять их необязательно. В качестве примера можно привес ти Perl и Visual Basic. Поскольку объектные возможности этих языков ограниче ны, в них вводится универсальный тип данных variant, с помощью которого обеспечивается абстракция. Однако появление такого типа нарушает принцип инкапсуляции, так как программа, принимающая данные типа variant, должна знать их внутреннюю структуру.
Работа с объектами в процедурных языках
Объектная технология — замечательная вещь, когда программа пишется на объектно ориентированном языке (таком как C++ или Java). Но это не всегда возможно. Что делать в подобном случае?
Объектная технология создавалась на базе более ранних технологий (абстрактное и модульное программирование), поэтому многие элементы ООП можно реализовать и в обычных процедурных языках. Но для этого требуется оп ределенная дисциплина программирования.
• Инкапсуляция. Необходимо представить все интерфейсы модуля в виде процедур или функций. Им следует присваивать имена вида
<имя_модуля>_<имя_функции>().
246 |
Часть III. Объектно ориентированные сокеты |
www.books-shop.com
•Абстракция. Если язык поддерживает операцию приведения типа, то аб стракцию можно обеспечить, записывая в одно из полей структуры идентификатор требуемого типа данных.
•Классы и объекты. Можно создать их прообразы, если в языке поддер живаются записи или структуры.
•Атрибуты. Это просто поля записи.
•Свойства. Для каждого опубликованного свойства необходимо создать связку функций Get( )/Set().
•Методы. Если в каком либо языке не поддерживаются функции (только процедуры), можно эмулировать их, возвращая значение через один из параметров процедуры.
•Отношения. Отношения включения и использования доступны в любом языке.
•Постоянство. Можно самостоятельно отслеживать параметры програм мы и загружать их при запуске.
•Потоковая передача. Чтобы упаковывать и распаковывать данные, необ ходимо знать их внутреннюю структуру и иметь возможность выполнять приведение типов.
•События и исключения. Можно эмулировать обработку событий и ис ключений, но для этого потребуется выполнять переходы между функ циями (например, с помощью функции setjump() в языке С), а это не
очень хорошая идея.
Резюме: объектно ориентированное
мышление
Объектная технология — это основа хороших программных разработок. Пра вильно применяя принципы ООП (абстракция, полиморфизм, наследование и инкапсуляция), можно создавать эффективные программные модули, которые бу дут многократно использоваться другими программистами. Кроме того, их легче отлаживать и расширять, чем обычные программы. Наконец, при объектно ориентированном подходе программист больше занят анализом предметной об ласти, чем собственно программированием.
Глава 11. Экономия времени за счет объектов |
247 |
www.books-shop.com
Глава Сетевое 12программирование в
Java
В этой главе... |
|
Работа с сокетами |
256 |
Ввод вывод в Java |
263 |
Конфигурирование сокетов |
265 |
Многозадачные программы |
266 |
Существующие ограничения |
269 |
Резюме |
269 |
www.books-shop.com
До сего момента вопросы сетевого программирования и, в частности, работы с сокетами рассматривались применительно к языку С. Его достоинства очевидны для системного программиста, но в результате получаются программы, которые не всегда переносимы и не всегда допускают многократное использование.
Java — прекрасный пример объектно ориентированного языка, в котором можно создавать многократно используемые, переносимые компоненты. В Java обеспечиваются два вида переносимости: на уровне исходного текста и на уровне кода. Переносимость первого типа означает, что все программы должны компилироваться на любой платформе, где поддерживается сам язык Java. (Компания Sun Microsystems оставляет за собой право объявлять некоторые ин терфейсы, методы и классы устаревшими и не рекомендуемыми для дальней шего использования.)
Концепция переносимости на уровне кода в действительности не нова. Прин цип "скомпилировал однажды — запускай везде" легко реализовать, имея соот ветствующие средства. Java программа компилируется в байт код, который вы полняется в рамках виртуальной машины. Виртуальная машина Java (JVM — Java Virtual Machine) интерпретирует каждую команду последовательно, подобно мик ропроцессору. Конечно, скорость интерпретации байт кода не сравнится со ско ростью выполнения машинных кодов (создаваемых компилятором языка С), но, поскольку современные процессоры обладают очень высоким быстродействием, потеря производительности не столь заметна.
Java — простой и в то же время интересный язык. Обладая навыками про граммирования в C/C++ и разбираясь в особенностях объектной технологии, можно быстро изучить его. В этом языке имеется очень мощный, исчерпываю щий набор стандартных библиотек классов, в котором не так то легко ориенти роваться. Поэтому не помешает всегда держать под рукой интерактивную доку ментацию по JDK (Java Development Kit — комплект средств разработки в среде Java) и несколько хороших справочников.
В предыдущей главе рассказывалось о назначении объектной технологии. В этой главе речь пойдет о том, как программировать сокеты в объектно ориентированной среде Java. Чтобы не вдаваться в чрезмерные детали, я предпо лагаю, что читатель знаком с Java и хочет изучать непосредственно сетевое про граммирование.
Прежде всего мы рассмотрим, какие классы существуют в Java для работы с сокетами, какие имеются средства ввода вывода, как конфигурировать сокеты и работать с потоками. /
Работа с сокетами
Многие программисты считают, что основные преимущества Java — независи мость от интерфейса пользователя и встроенные сетевые возможности. Предпоч тительным сетевым протоколом в Java является TCP. С ним легче работать, чем с дейтаграммами (протокол UDP), кроме того, это наиболее надежный протокол. В Java можно также посылать дейтаграммы, но напрямую подобная возможность не поддерживается базовыми библиотечными классами ввода вывода.
Глава 12. Сетевое программирование в Java |
249 |
www.books-shop.com
Программирование клиентов и серверов
Каналы потоковой передачи (TCP соединения) лучше всего соответствуют возможностям Java. Java пытается скрывать детали сетевого взаимодействия и уп рощает сетевые интерфейсы. Многие операции, связанные с поддержкой прото кола TCP, перенесены в библиотечные классы ввода вывода. В результате в соз дании сокетов принимает участие лишь несколько объектов и методов.
TCP$клиенты Java
Вот как, например, создается клиентский сокет:
Socket s = new Socket(String Hostname, int PortNum);
Socket s = new Socket(InetAddress Addr, int PortNum);
Самый распространенный вариант таков:
Socket s = new Socket("localhost", 9999);
Для подключения к серверу больше ничего не требуется. Когда виртуальная машина (ВМ) создает объект класса Socket, она назначает ему локальный номер порта, выполняет преобразование данных в сетевой порядок следования байтов и подключает сокет к серверу. Если требуется дополнительно указать локальный сетевой интерфейс и порт, то это делается так:
Socket s = new Socket(String Hostname, int PortNum,
InetAddress localAddr, int localPort);
Socket s = new Socket(InetAddress Addr, int PortNum,
InetAddress localAddr, int localPort);
Класс InetAddress преобразует имя узла или IP адрес в двоичный адрес. Чаще всего с объектом этого класса не работают напрямую, так как проще сразу вы звать конструктор Socket (), которому передается имя узла.
Поддержка стандартов IPv4/IPv6
В настоящее время Java поддерживает стандарт IPv4. Согласно проекту Merlin (информацию можно получить на Web узле java.sun.com), поддержка стандарта IPv6, появится, когда она бу дет внедрена в операционные системы. Классы наподобие InetAddress, осуществляющие пре образование имен, должны легко адаптироваться к новым протоколам. Но очевидно, что некото рые функции, например InetAddress.getHostAddress(), придется заменить при переходе на новый, расширенный формат адресов.
Прием/отправка сообщений
После создания объекта класса Socket программа еще не может посылать или принимать через него сообщения. Необходимо предварительно связать с ним входной (класс InputStream) и выходной (класс OutputStream) потоки:
InputStream i = s.getlnputstream();
OutputStream о = s.getOutputStream();
Чтение и запись данных осуществляются блоками:
250 |
Часть III. Объектно ориентированные сокеты |
www.books-shop.com