Но не менее важными оказались качественные изменения, связанные со смещением акцента использования компьютеров. Если в эпоху «больших машин» основными потребителями программного обеспечения были крупные предприятия, компании и учреждения, то позже появились персональные компьютеры и стали повсеместным атрибутом мелкого и среднего бизнеса. Вычислительные и расчетно-алгоритмические задачи в этой области традиционно занимали второстепенное место, а на первый план выступили задачи обработки и манипулирования данными.
Стало очевидным, что традиционные методы процедурного программирования не способны справиться ни с растущей сложностью программ и их разработки, ни с необходимостью повышения их надежности. Во второй половине 80-х годов возникла настоятельная потребность в новой методологии программирования, которая была бы способна решить весь этот комплекс проблем. Такой методологией стало объектно-ориентированное программирование (ООП).
Фундаментальными понятиями ООП являются понятия класса и объекта. При этом под классом понимают некоторую абстракцию совокупности объектов, которые имеют общий набор свойств и обладают одинаковым поведением. Каждый объект в этом случае рассматривается как экземпляр соответствующего класса. Объекты, которые не имеют полностью одинаковых свойств или не обладают одинаковым поведением, по определению, не могут быть отнесены к одному классу.
Важной особенностью классов является возможность их организации в виде некоторой иерархической структуры, которая по внешнему виду напоминает схему классификации понятий формальной логики. В этой связи следует заметить, что каждое понятие в логике имеет некоторый объем и содержание. При этом под объемом понятия понимают все другие мыслимые понятия, для которых исходное понятие может служить определяющей категорией или главной частью. Содержание понятия составляет совокупность всех его признаков или атрибутов, отличающих данное понятие от всех других. В формальной логике имеет место закон обратного отношения: если содержание понятия А содержится в содержании понятия В, то объем понятия В содержится в объеме понятия А.
Иерархия понятий строится следующим образом. В качестве наиболее общего понятия или категории берется понятие, имеющее наибольший объем и, соответственно, наименьшее содержание. Это самый высокий уровень абстракции для данной иерархии. Затем данное общее понятие некоторым образом конкретизируется, тем самым уменьшается его объем и увеличивается содержание. Появляется менее общее понятие, которое на схеме иерархии будет расположено на уровень ниже исходного понятия. Этот процесс конкретизации понятий может быть продолжен до тех пор, пока на самом нижнем уровне не будет получено понятие, дальнейшая конкретизация которого в данном контексте либо невозможна, либо нецелесообразна.
Примерами наиболее общих понятий могут служить такие абстрактные категории, как система, структура, интеллект, информация, сущность, связь, состояние, событие и многие другие. В процессе изучения этих категорий появляются новые особенности их содержания и объема. Именно по этим причинам всегда трудно дать им точное определение. В качестве примеров конкретных понятий можно привести понятие книги, которую читатель держит в руках, или понятие микропроцессора Intel Pentium П-300.
Основными принципами ООП являются наследование, инкапсуляция и полиморфизм. Принцип, в соответствии с которым знание о более общей категории разрешается применять для более узкой категории, называется наследованием. Наследование тесно связано с иерархией классов, которая определяет, какие классы следует считать наиболее абстрактными и общими по отношению к другим классам. При этом, если некоторый более общий или родительский класс (предок) обладает фиксированным набором свойств и поведением, то производный от него класс (потомок) должен содержать этот же набор свойств и поведение, а также дополнительные, которые будут характеризовать уникальность полученного таким образом класса. В этом случае говорят, что производный класс наследует свойства и поведение родительского класса.
Для иллюстрации принципа наследования можно привести следующий пример. Рассмотрим в качестве общего класс «Автомобиль». Данный класс определяется как некоторая абстракция свойств и поведения всех реально существующих автомобилей. При этом свойствами класса «Автомобиль» могут быть такие общие свойства, как наличие двигателя, трансмиссии, колес, рулевого управления. Если в качестве производного класса рассмотреть класс «Легковой автомобиль», то все выделенные выше свойства будут присущи и этому классу. Можно сказать, что класс «Легковой автомобиль» наследует свойства родительского класса «Автомобиль». Однако, кроме перечисленных свойств, класс-потомок будет содержать дополнительные свойства, например такое, как наличие салона с количеством посадочных мест 2-5.
В свою очередь, класс «Легковой автомобиль» способен порождать другие подклассы, которые вполне могут соответствовать, например, моделям конкретных фирм-производителей. Таким образом, можно рассматривать класс «Легковой автомобиль производства ВАЗ». Поскольку Волжский автомобильный завод выпускает несколько моделей автомобилей, одним из производных классов для предыдущего класса может быть конкретная модель автомобиля, например, ВАЗ-21083. Наконец, изготовленный автомобиль имеет уникальный заводской номер, отличающий один автомобиль от другого. Таким номером может быть, например, XTA-210830S1594301. В последнем случае класс будет состоять из единственного объекта или экземпляра, которым будет являться легковой автомобиль производства ВАЗ с указанным выше заводским номером.
Описанная выше информация о соотношении классов в нашем примере обладает одним серьезным недостатком, а именно отсутствием наглядности. В этой связи возникает вопрос: а возможно ли представить иерархию наследования классов в визуальной форме? Традиционно для изображения понятий в формальной логике использовались окружности или прямоугольники. Тогда для рассмотренного примера иерархия порождения классов может быть представлена в виде вложенных прямоугольников, каждый из которых соответствует отдельному классу (рис. 1.2).
Рис. 1.2. Иерархия вложенности классов для примера «Автомобиль»
Появление объектно-ориентированных языков программирования было связано с необходимостью реализации концепции классов и объектов на синтаксическом уровне. С точки зрения ООП класс является дальнейшим расширением структуры (structure) или записи (record). Включение в известные языки программирования С и Pascal классов и некоторых других возможностей привело к появлению соответственно C++ и Object Pascal, которые на сегодня являются наиболее распространенными языками разработки приложений. Распространению C++ и Object Pascal способствовало то обстоятельство, что язык C++ был выбран в качестве базового для программного инструментария MS Visual C++, а язык Object Pascal– для популярного средства быстрой разработки приложений Borland/Inprise Delphi.
За короткий период времени оба инструментария превратились в мощные системы разработки программ с соответствующими библиотеками стандартных классов, содержащих сотни различных свойств и методов. Применительно к среде MS Visual C++ 5/6 такая библиотека имеет специальное название – MFC (Microsoft Foundation Classes), т. е. фундаментальные классы от Microsoft. При этом производные классы наследуют свойства и методы родительских классов. Ниже приводится фрагмент иерархии классов MFC в том виде, как он изображен в соответствующей документации (рис. 1.3).
Рис. 1.3. Фрагмент иерархии классов MFC, используемых в среде программирования MS Visual C++ 5/6