Файл: Основные понятие объектно-ориентированного программирования.pdf
Добавлен: 01.04.2023
Просмотров: 316
Скачиваний: 1
СОДЕРЖАНИЕ
1. Основные понятия объектно-ориентированного программирования
2. Объект - как базовое понятие в объектно-ориентированном программировании
2.2 Наследование как важнейшее свойство объекта
2.3 Экземпляры объектных типов
4. Процесс объектно-ориентированного проектирования
5. Объектно-ориентированные языки
6. Особенности объектно-ориентированного проектирования
Спецификаторы public, private, protected Спецификаторы доступа private и public управляют видимостью элементов класса. Элементы, описанные после служебного слова private, видимы только внутри класса. Этот вид доступа принят в классе по умолчанию. Интерфейс класса описывается после спецификатора public. Действие любого спецификатора распространяется до следующего спецификатора или до конца класса. Можно задавать несколько секций private и public, порядок их следования значения не имеет. Поля класса: могут быть простыми переменными любого типа, указателями, массивами и ссылками (т.е. могут иметь практически любой тип, кроме типа этого же класса, но могут быть указателями или ссылками на этот класс); могут быть константами (описаны с модификатором const), при этом они инициализируются только один раз (с помощью конструктора) и не могут изменяться; могут быть описаны с модификатором static, но не как auto, extern и register. Инициализация полей при описании не допускается.
Глобальные и локальные классы Классы могут быть глобальными (объявленными вне любого блока) и локальными (объявленными внутри блока, например, внутри функции или внутри другого класса). Обычно классы определяются глобально. Локальные классы имеют некоторые особенности: локальный класс не может иметь статических элементов; внутри локального класса можно использовать из охватывающей его области типы, статические (static) и внешние (extern) переменные, внешние функции и элементы перечислений; запрещается использовать автоматические переменные из охватывающей класс области; методы локальных классов могут быть только встроенными (inline); если один класс вложен в другой класс, они не имеют каких-либо особых прав доступа к элементам друг друга и могут обращаться к ним только по общим правилам.
Примеры классов В качестве примера создадим класс, моделирующий персонаж компьютерной игры. Для этого требуется задать его свойства (например, количество щупалец, силу или наличие гранатомета) и поведение. Естественно, пример будет схематичен, поскольку приводится лишь для демонстрации синтаксиса. class monster { int health, ammo; public: monster(int he = 100, int am = 10) { health = he; ammo = am;} void draw(int x, int y, int scale, int position); int get_health(){return health;} int get_ammo(){return ammo;} }. В этом классе два скрытых поля – health и ammo, получить значения которых извне можно с помощью методов get_health() и get_ammo(). Доступ к полям с помощью методов в данном случае кажется искусственным усложнением, но надо учитывать, что полями реальных классов могут быть сложные динамические структуры, и получение значений их элементов не так тривиально. Кроме того, очень важной является возможность вносить в эти структуры изменения, не затрагивая интерфейс класса. Методы класса имеют неограниченный непосредственный доступ к его полям. Внутри метода можно объявлять объекты, указатели и ссылки как своего, так и других классов. В приведенном классе содержится три определения методов и одно объявление (метод draw). Если тело метода определено внутри класса, он является встроенным (inline). Как правило, встроенными делают короткие методы. Если внутри класса записано только объявление (заголовок) метода, сам метод должен быть определен в другом месте программы с помощью операции доступа к области видимости: void monster::draw(int x, int y, int scale, int position) { /* тело метода */} Встроенные методы можно определить и вне класса с помощью директивы inline (как и для обычных функций, она носит рекомендательный характер): inline int monster::get_ammo() { return ammo; } Методы можно перегружать (это одно из проявлений полиморфизма), а также объявлять либо константными, либо статическими (но не одновременно). В каждом классе есть метод, имя которого совпадает с именем класса. Он называется конструктором и вызывается автоматически при создании объекта класса. Конструктор предназначен для инициализации объекта. Автоматический вызов конструктора позволяет избежать ошибок, связанных с использованием неинициализированных переменных. Подробнее конструкторы описываются далее в разделе «Конструкторы». Типы данных struct и union являются специальными видами класса. Конкретные переменные типа данных «класс» называются экземплярами класса, или объектами. Время жизни и видимость объектов зависит от вида и места описания и подчиняется общим правилам С++: monster Vasia; // Объект класса monster с параметрами по умолчанию monster Super(200, 300);// Объект с явной инициализацией monster stado[100]; // Массив объектов с параметрами по умолчанию /* Динамический объект (второй параметр задается по умолчанию) */ monster *beavis = new monster (10); monster &butthead = Vasia;// Ссылка на объект При создании каждого объекта выделяется память, достаточная для хранения всех его полей, и автоматически вызывается конструктор, выполняющий их инициализацию. Методы класса не тиражируются. При выходе объекта из области действия он уничтожается, при этом автоматически вызывается деструктор (деструкторы описаны далее). Доступ к открытым (public) элементам объекта аналогичен доступу к полям структуры. Для этого используются операция . (точка) при обращении к элементу через имя объекта и операция -> при обращении через указатель: объект.поле указатель -> поле (*указатель).поле объект.метод( параметры ) указатель -> метод( параметры ) (*указатель).метод( параметры ) Обращение к открытому полю и вызов метода для массива объектов: имя_массива[ индекс ].поле имя_массива[ индекс ].метод( параметры ) Например: int n = Vasia.get_ammo(); stado[5].draw; cout << beavis->get_health(); Получить или изменить значения private элементов можно только через обращение к соответствующим методам. Можно создать константный объект, значения полей которого изменять запрещается. К нему должны применяться только константные методы: class monster { ... int get_health() const { return health; } }; const monster Dead (0,0); // Константный объект cout << Dead.get_health(); Константный метод: объявляется с ключевым словом const после списка параметров; не может изменять значения полей класса; может вызывать только константные методы; может вызываться для любых (не только константных) объектов. Рекомендуется описывать как константные те методы, которые предназначены для получения значений полей.
Классы могут быть глобальными (объявленными вне любого блока) и локальными (объявленными внутри блока, например, внутри функции или внутри другого класса). Обычно классы определяются глобально.
Локальные классы имеют некоторые особенности: локальный класс не может иметь статических элементов; внутри локального класса можно использовать из охватывающей его области типы, статические (static) и внешние (extern) переменные, внешние функции и элементы перечислений; запрещается использовать автоматические переменные из охватывающей класс области; методы локальных классов могут быть только встроенными (inline) Класс, содержащий хотя бы один чисто виртуальный метод, называется абстрактным.
Абстрактные классы предназначены для представления общих понятий, которые предполагается конкретизировать в производных классах. Абстрактный класс может использоваться только в качестве базового для других классов – объекты абстрактного класса создавать нельзя, поскольку прямой или косвенный вызов чисто виртуального метода приводит к ошибке при выполнении. При определении абстрактного класса необходимо иметь в виду следующее: Абстрактный класс нельзя использовать при явном приведении типов, для описания типа параметра и типа возвращаемого функцией значения. Допускается объявлять указатели и ссылки на абстрактный класс, если при инициализации не требуется создавать временный объект. Если класс, производный от абстрактного, не определяет все чисто виртуальные функции, он также является абстрактным. Таким образом, можно создать функцию, параметром которой является указатель на абстрактный класс. На место этого параметра при выполнении программы может передаваться указатель на объект любого производного класса. Это позволяет создавать полиморфные функции, работающие с объектом любого типа в пределах одной иерархии; если один класс вложен в другой класс, они не имеют каких-либо особых прав доступа к элементам друг друга и могут обращаться к ним только по общим правилам.
4. Процесс объектно-ориентированного проектирования
Объектно-ориентированное проектирование (Object-Oriented Design - OOD) - это поступательный итеративный процесс. Граница между объектно-ориентированным анализом и проектированием расплывчата и построение проекта программного изделия состоит из ряда циклов, в которых уточняются описания классов и взаимодействия между ними, разрабатываются реализующие их программы, проводится их отладка и тестирование и по результатам каждого этапа уточняются рабочие документы предыдущих этапов, дорабатываются описания классов и программы. Эти циклы повторяются до получения требуемого результата.
В рассмотренном выше примере были выделены классы “множество данных” и “данное”. Пусть классу “множество данных” присвоено имя TXSet.
С учетом имеющихся инструментальных средств класс TXSet может быть построен на основе класса Array из библиотеки CLASSLIB, т.е. это множество может быть интерпретировано массивом. Массив представляет собой упорядоченную совокупность однотипных элементов, в то же время данные могут принадлежать различным типам и каждому тип соответствует свой набор характеристик. Это противоречие можно преодолеть, если элементами массива TXSet будут указатели на экземпляры данных.
Чтобы использовать указатели на экземпляры данных как элементы массива, все классы, определяющие типы данных, должны быть образованы из общего базового класса.
Пусть требуется обеспечить возможность использования числовых скалярных данных и массивов (векторов и прямоугольных матриц), а также данных типа строк и массива строк. Естественно определить для каждого такого типа свой класс: TDScal, TDArray, TDString, TDStringArray. В каждом из этих классов должно быть поле идентификатора данного ident, поле описания данного head и, возможно, поле flags, представляющее собой набор битов, дополняющих описание данного. Может оказаться удобным иметь и поля, содержащие количество знаков при представлении скаляра или элементов массивов (width) и количество цифр в дробной части для представления чисел (dec). Все эти данные можно объединить в классе TData, базовом для остальных классов данных. Таким образом, вместо одного класса “данное”, выделенного на этапе анализа, появилось пять классов. После этого следует вернуться к этапу анализа и оформить рабочие документы анализа для новых классов.
Аналогичным образом следует уточнить состав и определения остальных классов, выбранных на этапе анализа.
После определение перечня классов следует разработать семантику каждого класса - определить состав и назначение методов класса. При этом также может возникнуть необходимость выделения новых классов и, следовательно, повторение отдельных частей этапа анализа и новое уточнение ранее описанных классов.
Таким образом, процесс объектно-ориентированного проектирования состоит из циклического выполнения четырех основных шагов:
- Определение классов и объектов на определенном уровне абстракции.
- Определение семантики классов.
- Определение (идентификация) связей между классами и объектами.
- Реализация классов.
На каждом повторении этого цикла уточняются описания классов и перерабатываются проектные документы.
Объектно-ориентированное проектирование--это только часть объектно-ориентированного процесса разработки системы, где на протяжении всего процесса создания ПС используется объектно-ориентированный метод. Этот подход подразумевает выполнение трех этапов:
1. Объектно-ориентированный анализ - создание модели предметной области приложения ПС, где объекты отражают реальные объекты - сущности, а также определяются операции, выполняемые объектами.
2. Объектно-ориентированное программирование -- реализация архитектуры системы с помощью объектно-ориентированного языка программирования непосредственно выполняющего отражение определенных объектов и предоставляющего средства для определения классов объектов.
3. Объектно-ориентированное проектирование -- разработка модели системы программное средство и системной архитектуры с учетом системных требований, в которой определение всех объектов подчинено решению конкретной задачи.
При ООП основное внимание уделяется тому, что следует делать, каким образом добиться цели, а процесс её достижения целиком зависит от этапа разработки. Объектная декомпозиция дает возможность создавать программные комплексы визуально меньшего размера путем использования общих механизмов, обеспечивающих необходимую экономию выразительных средств. Использование объектного подхода повышает уровень унификации разработки и пригодность для повторного использования не только программных компонентов, но и больших комплексов программ, что ведет к созданию унифицированной среды разработки и переходу к сборочному созданию программных продуктов. Системы зачастую получаются более компактными, чем их структурные эквиваленты, что означает не только уменьшение объема программного кода, но и удешевление проекта за счет использования компонентов из предыдущих разработок. Однако, структурный подход сохраняет свою высокую значимость и широко используется на практике. Взаимосвязью между структурным и объектно-ориентированным подходами является общность ряда категорий и понятий жизненного цикла ПС.
В программных средствах при ООП рекомендуется выделять три уровня:
1. Уровень интерфейсов, который занимается всеми взаимодействиями с другими частями системы и предоставлением внешних интерфейсов системы.
2. Уровень сбора данных, управляющий сбором информации из внешней среды и обобщающий данные перед отправкой их в систему построения обобщенных результатов.
3. Уровень объектов, в котором представлены и описаны все объекты, используемые в процессе сбора исходных данных.
5. Объектно-ориентированные языки
Инкапсуляция, наследование и полиморфизм — фундаментальные свойства, требуемые от языка, претендующего называться объектно-ориентированным. (Языки, не имеющие наследования и полиморфизма, но имеющие только классы, обычно называются основанными на классах.) Различные объектно-ориентированные языки используют совершенно разные подходы. Мы можем различать объектно-ориентированные языки, сравнивая механизм контроля типов, способность поддерживать различные программные модели и то, какие объектные модели они поддерживают. Языки объектного программирования принято делить на объектные, в которых существуют классы и объекты, и объектно-ориентированные, в которых программист может не только пользоваться предопределёнными классами, но и задавать собственные пользовательские классы (либо создавать объекты, устройство которых отличается от устройства прототипов — в языках прототипного программирования).
Объектное и объектно-ориентированное программирование возникло в результате развития идеологии процедурного программирования, где данные и подпрограммы (процедуры, функции) их обработки формально не связаны. Кроме того, в современном объектно-ориентированном программировании часто большое значение имеют понятия события (так называемое событийно-ориентированное программирование) и компонента (компонентное программирование).
Объектно-ориентированное программирование в настоящее время является абсолютным лидером в области прикладного программирования (языки Java, C#, C++, JavaScript, ActionScript и др.). В то же время в области системного программирования до сих пор лидирует парадигма процедурного программирования, и основным языком программирования является язык C. Хотя при взаимодействии системного и прикладного уровней операционных систем заметное влияние стали оказывать языки объектно-ориентированного программирования. Например, мультиплатформенным стандартом стала система Qt, написанная на языке C++.
Си++ - это универсальный язык программирования, задуманный так, чтобы сделать программирование более приятным для серьезного программиста. За исключением второстепенных деталей Си++ является надмножеством языка программирования Cи. Помимо возможностей, которые дает Cи, Си++ предоставляет гибкие и эффективные средства определения новых типов. Используя определения новых типов, точно отвечающих концепциям приложения, программист может разделять разрабатываемую программу на легко поддающиеся контролю части. Такой метод построения программ часто называют абстракцией данных. Информация о типах содержится в некоторых объектах типов, определенных пользователем. Такие объекты просты и надежны в использовании в тех ситуациях, когда их тип нельзя установить на стадии компиляции. При правильном использовании этот метод дает более короткие, проще понимаемые и легче контролируемые программы.