TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

Объектно-ориентированное программирование:

предыстория, три кита - инкапсуляция, наследование и полиморфизм, а так же незаменимый механизм; выводы

 

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

Предыстория

 

Довольно давно, практически сразу после появления языков третьего поколения (в 67 году), умным людям пришла в голову идея несколько преобразовать постулат фон Неймана о том что данные и программы неразличимы в памяти машины. Они решили: пусть данные и программы если не станут одним и тем же, то сильно к этому приблизятся. Правда делали они все это не от хорошей жизни и за деньги - разрабатывали сложную систему моделирования сложной системы (то есть столкнулись с задачей, решение которой без декомпозиции оказалось невозможно). Попытки обосновать декомпозицию и привели к уже полученным нами выводам. Недостатком здесь являлась чрезмерная размытость подхода, его объяснение скорее на уровне понимания и интуиции, чем на уровне правил (1). Усилия многих программистов и системных аналитиков, направленные на формализацию подхода, увенчались успехом.

Были разработаны три основополагающих принципа того, что потом стало называться объектно-ориентированным программированием (ООП): наследование, инкапсуляция, полиморфизм.

Результатом их первого примениния стал язык Симула-1 (Simula-1), в котором был введен новый тип - объект. В описании этого типа одновременно указывались данные (поля) и процедуры, их обрабатывающие - методы. Родственные объекты объединялись в классы, описания которых оформлялись в виде блоков программы. При этом класс можно использовать в качестве префикса к другим классам, которые становятся в этом случае подклассами первого. Впоследствии Симула-1 был обобщен и появился первый универсальный ООП ориентированный ЯП - Симула-67 (67 - по году создания).

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

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

Разберем три принципа, которые стали почти достаточными для реализации концепции ООП. Предварительно введем определения слов "объект" и "класса".

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

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

Инкапсуляция

 

Несмотря на непривычность слова просто связывание полей и методов в одну структуру (складывание их в одну "капсулу"). Это удобно, хотя и без остальных двух принципов никакого нового качества программирования не дает. Действительно, если объединить данные хотя бы с алгоритмами доступа к ним, то программист окажется независимым от представления данных в объекте: объект становится абстракцией представления соих собственных данных.

В более общем случае объекту можно приписать свойства (методы), абстрагирующие не только представление, но и придающие объекту другие свойства, к примеру способность отображаться.

Теоретически принцип инкапсуляции применим как к отдельным объектам, так и к классам. В случае классов с методами объединяются не сами данные, а структуры данных, и объединение с конкретными данными происходит в момент создания объектов данного класса. На практике же большинство ОО языков просто не позволяют создавать объекты, не создав предварительно класса.

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

 

Этот принцип отностится только к классам объектов.

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

Наследование бывает двух видов:
одиночное - когда каждый класс имеет одного и только одного предка;
множественное - когда каждый класс может иметь любое количество предков.

 

Множественное наследование обладает более мощными возможностями: в одном классе-наследнике объединяюстся свойства (поля и методы) множества различных классов. К примеру один из предков может рисовать себя, а другой - производить вычисления. представитель их наследника смогут делать и то, и другое.

Полиморфизм

 

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

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

Позднее связывание

 

Несмотря на то, что три перечисленных принципа называют "тремя китами ООП", сами по себе они не имеют смысла без наличия особого механизма, названного поздним (динамическим) связыванием. Приведем пример.

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

Действительно, в момент компиляции нашей программы, мы жестко определяем, что при вызове метода доступа к элементу объекта класса "матрица" вызывается метод объекта класса-наследника "двумерный массив". Даже если мы разместим по тем же адресам (или передадим в качестве параметров) объекты других классов-наследников ("блочная матрица", например), все равно будет вызываться метод класса "двумерный массив". Что и приведет к краху программы.

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

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

 

Выводы

 

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

Объектно-ориентированное программирование базируется на трех принципах и одном механизме: инкапсуляция, наследование, полиморфизм и позднее связывание. (Иногда к ним приписывают программирование, управляемое сообщениями).

Объектно-ориентированный подход к программированию подразумевает выделение общих свойств у различных объектов и широчайшее применение абстракций всех уровней.

(1) Обратно Авторы прекрасно понимали, что пользоваться их теоретическими разработками будут обыкновенные программисты, для которых наличие правил является едва ли не необходимым условием применимости того или иного средства.

 

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz