Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекцій.doc
Скачиваний:
16
Добавлен:
03.11.2018
Размер:
1.12 Mб
Скачать

2.1 Елементи концепції ооп.

Об’єктно-орієнтована парадигма пропонує новий підхід до розробки програмного забезпечення. Фундаментальна концепцiя об’єктно-орієнтованої парадигми полягає в передачi повiдомлень об'єктам. Для цього необхiдно, щоб процедури визначались в одному програмному об’єкті разом з даними, якими вони маніпулюють. Відмітимо, що в процедурному програмуванні спочатку визначаються структури даних, якi потiм передаються в процедури як параметри.

Iснує п'ять компонент об’єктно-орієнтованої парадигми (парадигма-концепція):

1 - об'єкт ;

2 - повiдомлення ;

3 - клас ;

4 - наслiдування ;

5 - метод .

Будь-яка об’єктно-орієнтована мова повинна мати властивостi абстракцiї, iнкапсуляцiї, наслiдування та полiморфiзму.

Об’єкт - це iнкапсульована абстракцiя , яка включає iнформацiю про стан та чітко визначену множину протоколу доступу (повiдомлення, яке обробляє об'єкт.)

Повідомлення - це спецiальний символ, iдентифiкатор чи ключове слово (може бути з параметрами чи без), яке представляє дiю , що виконується об'єктом.

Клас представляє собою певний тип об'єктiв i задається за допомогою опису

класу. Опис класу визначає змiннi стану та протокол доступу до об'єктiв даного класу. Класи органiзовуються iєрархiчно, причому похідні класи наслiдують властивостi класiв, що їх породжують. В деяких ОО-мовах класи є також об'єктами.

Метод існує для кожного повідомлення, визначеного для деякого класу. Він визначає реакцiю об'єкта на повiдомлення. Як правило, метод складається з ряду виразів і може використовувати протокол з іншого класу.

Таким чином, об’єкти належать до окремих класів. Об’єкти обробляють повідомлення у відповідності з методами, заданими в описі класу. Об’єкти мають змінні стану, визначені в описі класу. Змінні стану можуть мати однакові чи різні значення в різних об’єктів (екземплярів класу).

Розглянемо основні поняття об’єктно-орієнтованої парадигми по відно -шенні до С++.

Клас - це новий тип даних , який вводиться за допомогою ключового слова class.

Об’єкт - це змiнна типу ClassName, де ClassName - це ім’я ранiше визначе- ного класу.

Змінні стану - це змiннi, якi оголошенi в описi класу. Будемо називати їх полями даних .

Повідомлення , на якi може реагувати об'єкт, вказується за допомогою прототипiв функцiй в описi класу. Тобто, фактично, повідомлення - це набори фактичних значень, що відповідають сигнатурам функцій-членів класу.

Метод - це визначення(реалізація) функцiї-члена класу.

Абстрагування - це формування представлення про якостi чи властивостi предмету шляхом мисленного видiлення деяких його часткових рис.

Iнкапсуляція - це об'єднання , закриття в "капсулi" певних конструкцій.

Наслідування - це властивiсть похiдного класу наслiдувати властивостi базового класу. При цьому похiдний клас може мати якiсь свої специфiчнi властивостi. Ця властивiсть дає можливiсть утворювати iєрархiю класiв . Iснує поняття множинного наслiдування, коли похiдний клас може бути породжений кiлькома базовими.

Потрiбно розрiзняти наслiдування та контейнернi вiдношення. Якщо клас 1 має всi властивостi класу 0, i крiм того , якiсь свої додатковi, то в такому випадку оправдана iєрархiчна структура( наслiдування).

class 1 <- class 0

Про контейнерне вiдношення говорять, якщо об'єкт класу class 0 мiстить об'єкт класу class 1 , тобто одне з полiв класу class0 має тип class 1.

Поліморфізм - цє здатність повiдомлення викликати рiзнi дiї (реакції методів) на етапi виконання програми . Тобто конкретна форма реакції на повiдомлення визначається i зв'язується з об'єктом пiд час виконання програми (пiзнє зв'язування). В С++ поліморфізм проявляється у підтримці наступних механізмів:

1. Перегрузка функцiй (всерединi опису класу можна перегружати функцiї).

2. Перегрузка операцiй.

3. Вiртуальнi функцiї.

2.2 Від структур ANSI С до класів С++.

Синтаксичною основою реалізації концепції об’єктно-орієнтованого програмування стало введення в С++ нових властивостей структур та класів. Розглянемо, як можна прийти до розуміння необхідності цих властивостей, виходячи з точки зору ідеології об’єктно-орієнтованого програмування, поняття об‘єкта. Нехай описана, наприклад, така структура:

struct TTime {

int year;

int month;

int day;

int hour;

int minute; };

TTime v;

Очевидно, що змінна v може використовуватись для збереження інформації про певний час (рік, місяць, день, година, хвилина). Безсумнівно, що нам може бути необхідною функція, яка виводить цю інформацію в певній формі на якийсь стандартний пристрій виводу (монітор, наприклад):

void Display (TTime*p)

{printf ("year=%d month=%d day=%d hour=%d \

minute=%d \n", p-> year, p-> month, p-> day,\

p-> hour ,p-> minute);}

Проте, функція Display семантично дуже пов’язана з структурою Ttime. Це наводить на думку пов’язати функцію з структурою синтаксично. В С++ (на відміну від ANSI C) є така можливість: функцію можна записувати як поле структури. Тоді наш приклад можемо переписати так:

struct TTime {

int year;

int month;

int day;

int hour;

int minute;

void Display (void)

{printf ("year=%d month=%d day=%d hour=%d \

minute=%d \n", p--> year, p--> month, p--> day,\

p--> hour ,p--> minute);}

};

Можна записати функцію-член структури , визначивши її за межами формального опису структури з використанням операції розширення області видимості:

struct TTime {

int year;

int month;

int day;

int hour;

int minute;

void Display (void);

};

void TTime::Display (void)

{printf ("year=%d month=%d day=%d hour=%d \

minute=%d \n", p--> year, p--> month, p--> day,\

p--> hour ,p--> minute);}

Що ж ми отримали ? Зробивши функцію членом структури , ми не внесли нічого нового з точки зору можливостей . Адже будь-яка зовнішня функція має вільний доступ до полів даних структури (через операцію “.”). Все те, що можна робити з даними за допомогою функції-члена структури можна робити і за допомогою зовнішніх функцій . Проте, в семантичному плані це безсумнівне досягнення. Об’єднання даних та функцій , що працюють з цими даними в одній структурі - це приклад інкапсуляції. Функція-член структури стає ніби властивістю структури. А що ж це за структура, що має якісь властивості? Де її можна використовувати? Очевидно, що такі структури могли б бути корисними для моделювання реальних природних об’єктів. В нашому випадку, наприклад, структура TTime з функцією-членом Display може служити моделлю годинника. Тобто об’єкта, при звертанні до якого ми отримуємо інформацію про час та дату. Але очевидно, що природні об’єкти мають дані, які є скритими від певних зовнішніх об’єктів. Наприклад, спостерігаючи за літаком, можна визначити його швидкість, висоту, тип, але не можна ззовні визначити, скільки у нього залишилося пального та боєприпасів. Тоді приходимо до думки, що деякі поля даних повинні бути закритими. Тобто недопустимим синтаксично повинне бути звертання до цих полів за допомогою, наприклад, операції “ . ”. Так, виходячи з поняття інкапсуляції, приходимо до концепції закритих полів даних. В С++ існують спеціальні службові слова - специфікатори доступу: public, protected та private. Дані, розміщені в розділах protected та private стають доступними лише для функцій-членів і недоступними для зовнішніх функцій. Доступ до них може здійснюватись лише за допомогою функцій, описаних у відкритому розділі.

Оголосимо поля даних в нашому прикладі закритими:

struct TTime {

private:

int year;

int month;

int day;

int hour;

int minute;

public:

void Display (void);

} tt1;

void TTime::Display (void)

{printf ("year=%d month=%d day=%d hour=%d \

minute=%d \n", p--> year, p--> month, p--> day,\

p--> hour ,p--> minute);}

Тоді при звертанні виду tt1.day компілятор видасть повідомлення про помилку.

Концепція закритих даних є значним кроком вперед з точки зору теорії програмування. Адже в класичному процедурному програмуванні діє правило: дані формують код. Тобто спочатку визначаються структури даних, з якими доводиться працювати, а потім пишуться функції роботи з ними. При такому підході програма стає надзвичайно залежною від структур даних. Припустимо, наприклад, що ми написали величезну кількість функцій, що працюють з полями структури TTime. Але ж дату можна зберігати і в секундах, використовуючи змінну типу long . Уявімо собі, скільки змін потрібно внести в програму, щоб реалізувати цю ідею. Адже потрібно змінювати всі функції типу Display , всі оператори, які звертаються до полів. У випадку ж закритих даних змінити доведеться лише функції-члени структури, які працюють з закритими даними. Все інше може залишитися без змін ! Більше того, можна взагалі писати програму, визначаючи спочатку функціональний інтерфейс і лише на останньому кроці визначати внутрішню структуру закритих даних. Обмеженість впливу даних на код є однією з суттєвих особливостей ООП.

Відмітимо, що структури та класи в С++ мають лише незначні відмінності у властивостях. Іх можна розуміти не лише як типи даних, але і як синтаксично допустимий спосіб утворення типів даних користувача. В С++ ім’я структури чи класу - це тип даних. Якщо, наприклад, в ANSI C хочемо оголосити змінну типу struct TTime, то можемо написати оголошення виду: struct TTime a; Тут обов’язковим є ключове слово struct. В С++ слово struct не обов’язкове. Тобто допускається еквівалентне оголошенння виду: TTime а; Для можливості такого оголошення в ANSI C потрібно використовувати засіб typedef:

typedef struct TTime {

... };

TTime a;