Тема 4. Способи повторного використання коду

Основні поняття

Композиція

Наслідування

Батьківський клас

Дочірній клас

Перевизначення

Абстрактний клас

Композиція

 

Якщо екземпляр одного класу є полем іншого класу, вважається, що між класами є певна залежність. Її можна використати у програмі як спосіб побудови нових класів. Такий спосіб повторного використання коду називається композицією. При цьому встановлюється відношення між об’єктами цих класів – “бути частиною” (англ. pаrt of).

 

Приклад:

 

type TRectangle=class

Points: array [1..4] of TPoint; // об’єкти-точки є полями // класу прямокутників

// …

end;

 

var R1: TRectangle;

X1: Real;

// …

X1:=R1.Points[1].X;

 

Наслідування

Якщо будь-який екземпляр одного класу (T1) є водночас екземпляром іншого класу (T2), але не навпаки, то вважається, що між двома класами існує залежність: другий клас називається батьківським класом, а перший – дочірнім.

 

Приклад

 

TRectangle=class(TQuadrangle);

// …

End;

 

У даному прикладі TQuadrangle – батьківський клас, TRectangle – дочірній (кожен прямокутник є чотирикутником).

Такий спосіб повторного використання коду називається наслідуванням(англ. inheritance). Відношення між об’єктами цих класів – “бути”(англ. is a).

Наслідування – це можливість доступу об’єктів дочірнього класу до полів та методів батьківського класу. Наприклад, якщо поле Points оголошено в класі TQuadrangle, до нього можуть також звернутись об’єкти класу TRectangle. Такі поля та методи називаються успадкованими. Також дочірній клас може мати додаткові поля та методи

Клас може успадковувати поля та методи класів віддалених від нього на декілька рівнів.

 

Приклад ієрархії класів:

 

TPolygon → TQuadrangle → TRectangle → TSquare

 

Клас TSquare успадковує поля та методи класів TPolygon, TQuadrangle та TRectangle.

Перевизначення методів. Абстрактні методи та класи

Розглянемо приклад. Нехай існує наступна ієрархія класів:

 

TFigure → TClosedFigure → TPolygon → TQuadrangle → TRectangle → TSquare

У класах описані наступні поля та методи:

TFigure: Origin, Points (поля), Draw та Rotate (методи);

TClosedFigure Perimeter (метод);

TQuadrangle Diagonal1, Diagonal2 (методи);

TRectangle Side1, Side2 (поля або методи).

 

Тоді:

 

Поля Points та Origin, методи Draw та Rotate, успадковуються усіма дочірніми класами.

Метод Perimeter є доступним для класу TClosedFigure та його дочірніх класів.

Метод Diagonal є доступним для класу TQuadrangle та його дочірніх класів.

 

Дочірні класи можуть змінювати поведінку, яка успадкована від батьківського класу – інакше реалізовувати або перевизначати методи. Щоб дозволити перевизначення, у батьківському класі такий метод має бути позначений ключовим словом virtual (віртуальний метод). Метод, що перевизначається, у дочірньому класі має бути позначений ключовим словом override.

Якщо реалізація методів, які належать до класів на верхніх рівнях ієрархії є достатньо складною або неможливою і методи перевизначаються в дочірніх класах, то ці методи у батьківських класах можна описати, але не реалізовувати.

Такі методи батьківського класу називаються абстрактними і позначаються ключовим словом abstract. Клас, у якому є хоча б один абстрактний метод, називається абстрактним. Якщо абстрактним є конструктор, то об’єкти цього класу не створюють.

 

type

TFigure=class

//…

procedure Draw; virtual; abstract;

procedure Rotate (X, Y, Angle: Real); virtual; abstract;

end;

TClosedFigure=class(TFigure)

// …

function Perimeter: Real; virtual;

// …

end;

TPolygon=class(TClosedFigure)

//…

end;

TQuadrangle=class(TPolygon)

// …

procedure Draw; override;

procedure Rotate (X, Y, Angle: Real); override;

end;

TRectangle=class(TQuadrangle)

// …

function Perimeter: Real; override;

//…

end;

 

Реалізація перевизначеного методу Perimeter у класі TRectangle може бути наступною:

 

function TRectangle.Perimeter: Real;

begin

Perimeter:=(Side1+Side2)*2;

end;

 

Способи перевизначення методів

  1. Заміщення - метод дочірнього класу (ДК) повністю заміщує метод батьківського класу (БК) Приклад – обчислення площі прямокутника у порівнянні з обчисленням площи довільної замкненої фігури.
  2. Уточнення – метод ДК містить виклик метода БК (позначається ключовим словом inherited). Приклад – метод малювання заповненого прямокутника викликає метод малювання контура з батьківського класу прямокутників і додає код для заповнення:

 

type

TFilledRectangle=class(TRectangle)

{…}

 

procedure TFilledRectangle.Draw;

begin

inherited Draw;

Fill;

end;

 

Тема 5. Гнучкість коду

Основні поняття

Поліморфізм

Статичний тип

Динамічний тип

Зв’язування

Перевантаження

 

Поліморфізм. Принцип підстановки і поліморфне присвоєння. Статичні та динамічні типи.

Наслідування надає можливість використовувати у діях над об’єктами наступне правило (принцип підстановки):

Якщо є два класи А і В, такі, що клас В є дочірнім для класу А, то ми можемо підставити об’єкт класу В замість об’єкта класу А у будь-якій ситуації без видимої різниці.

Отже змінній-об’єкту батьківського класу завжди можна надати значення іншого типу (дочірнього класу).

Така можливість змінної або аргументу функції містити під час виконання програми значення різних типів називається поліморфізмом (англ. polymorphism); змінна – поліморфною, а надання цій змінній значення іншого типу – поліморфним присвоєнням.

Згідно з принципом підстановки поліморфне присвоєння є можливим від об’єкта ДК до об’єкта БК, але не навпаки !

 

Приклад:

 

var P1, P2: TPolygon; R1, R2: TRectangle;

// …

P1:=R1; // коректно

R2:=P2; // не коректно

 

Після присвоєння P1:=R1, вважається , що клас TPolygon – це статичний тип змінної P1, а клас TRectangleдинамічний тип цієї змінної.

В Object Pascal статичний і динамічний типи при оголошенні змінних збігаються. При поліморфному присвоєнні відбувається зміна динамічного типу.

 

Пересилання повідомлень. Зв’язування повідомлення і метода.

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

 

Приклад:

 

var P1: TPolygon; R1: TRectangle;

X1: Real;

// …

P1:=R1;

X1:= P1.Perimeter; // об’єкт P1 - одержувач повідомлення Perimeter

 

Виклик P1.Perimeter є коректним лише тоді, коли метод Perimeter оголошений у класі об’єкта P1 (TPolygon)або в одному з його батьківських класів, тобто коректність повідомлення перевіряється по статичному типу.

Реалізація методу Рerimeter береться з класу TRectangle – за динамічним типом змінної. Тоді повідомлення Рerimeter зв’язується з реалізацією з класу TRectangle, отже зв’язування є динамічним.

 

Приклад:

 

var Figures: array [1..4] of TFigure;

R: TRectangle; T: TTriangle; E: TEllipse; S: TSquare;

//…

Figures[1]:= R;

Figures[2]:= T;

Figures[3]:= E;

Figures[4]:= S;

for i:=1 to 4 do

Figures[i].Draw;

 

В результаті будуть по черзі викликані 4 реалізації методу Draw з різних класів (в залежності від динамічного типу), але при цьому потрібно, щоб метод Draw був оголошений (навіть абстрактним) у класі, який відповідає статичному типу.

 

Визначення динамічного типу об’єкта.

 

Щоб дізнатися динамічний тип об’єкта, використовується метод класу TObject:

function ClassName: ShortString;

або оператор is, наприклад:

 

var P: TPolygon; R:TRectangle;

//…

P:=R;

 

if P is TRectangle then (P as TRectangle).Side1:=10;

 

Оператор is поверне true, коли змінна P має динамічний тип TRectangle або один з його дочірніх класів.

Оператор as при цьому виконає безпечне приведення змінної p до типу TRectangle.

 

Перевантаження операторів

У наведених вище прикладах, методи що викликалися, записувалися однаково для об’єктів різних класів, тобто вважалися ніби однією функцією (“чистий поліморфізм”). Можливий інший варіант, коли одне ім’я мають декілька різних функцій. Цей випадок називається перевантаженням.

У програмуванні використовують перевантаження операторів, а в ООП – перевантаження методів.

Приклад перевантаження операторів є '+':

5 + 3 = 8 // для чисел

'5' + '3' = '53' // для символьних рядків

(5) + (3) = (3, 5) // для множин

Результат буде залежати від типів аргументів.

 

Перевантаження методів

На мові Object Pascal усі методи, які перевантажуються, позначаються ключовим словом overload. Якщо метод, що перевантажується, оголошується в дочірньому класі, то крім ключового слова overload слід вказати ключове слово reintroduce.

Приклад:

 

type

TNumber=class

function Add (X, Y: Integer): Integer; overload; // метод 1

Function Add (X, Y: Real): Real; overload; // метод 2

Function Add (X: Integer; Y: Real): Real; overload; // метод 3

Function Add (X: Real; Y: Integer): Real; overload; // метод 4

End;

 

Var N: TNumber;

A: Integer; B: Real;

 

A:=N.Add(1, 2); //виклик 1 методу

B:=N.Add(1.0, 2.0); //виклик 2 методу

B:=N.Add(1, 2.0); //виклик 3 методу

B:=N.Add(1.0, 2); //виклик 4 методу

 

Метод, що викликається, залежить від типів аргументів, а також від послідовності і кількості. При цьому назви формальних параметрів (наприклад X, Y) значення не мають.

 

Тема 6. Механізми контролю над складністю програми

Основні поняття

Абстрактний тип даних

Модуль

Зачеплення

Звязність

 

Перша мова програмування – Assembler. У Assembler з ускладненням програмного забезпечення практично неможливо пам’ятати всю інформацію для написання та відлагодження програми. Тому виникли інші мови програмування, наприклад, Fortran (працює з підпрограмами).

 

Сучасний підхід (Pascal, C)

- Програма розбивається на процедури та функції;

- В програмі виділяються абстрактні типи даних;

- Програма розділяється на модулі.

Абстрактний тип даних (АТД) – це множина елементів, описана переліком властивостей цих елементів та переліком функцій, які можна застосувати до них.

АТД задається програмістом і використовується так само як і типи даних, вбудовані в систему. Прикладами АТД є комплексні числа (Re, Im), двовимірні масиви (матриці).

Модулі (англ. units) – це окремі частини програми; мають такі особливості:

- можуть компілюватися окремо, але встановлювати зв’язки з іншими модулями (через директиву uses);

- імена типів, змінних процедур, функцій розділяються на дві частини: відкриту (interface) – доступну ззовні модуля, і закриту (implementation) – доступну тільки всередині модуля.

В ООП до відкритої частини відносять опис того, що може робити модуль, до закритої – реалізацію завдань модуля. Цей принцип має назву маскування інформації.

Класи поєднують можливості АТД та модулів. Так як і для АТД можна створити змінну цього типу, подібно до модулів існує поділ на приховану та видиму частину.

 

Характеристики модулів

1. Зачеплення – міра взаємозв’язків між різними модулями.

2. Зв’язність – міра взаємозв’язків всередині модулів.

Вважається, що сума цих мір є сталою для певної задачі, тобто чим більша зв’язність, тим менше зачеплення і навпаки.

Модуль вважається якісним, якщо зв’язність висока, а зачеплення низьке.

 

Різновиди зачеплення

  1. По внутрішніх даних (один з модулів змінює локальні дані іншого).
  2. По глобальних даних (глобальні змінні є спільними).
  3. При керуванні (порядок виконання операції в одному модулі залежить від іншого).
  4. По параметрах (один з модулів викликає підпрограми та функції з іншого, дані передаються як параметри).
  5. Через підкласи (в одному з модулів створюються підкласи до класів з іншого модуля).

Найприйнятніший варіант 5, далі – 4, 3, 2, 1.

 

Різновиди зв’язності

  1. За суміщенням (елементи групуються без особливої причини).
  2. Логічна (є логіка, наприклад, бібліотека математичних функцій).
  3. Часова (елементи використовуються приблизно одночасно, наприклад, блок ініціалізації програми).
  4. Комунікаційна (елементи модуля працюють з одними пристроями).
  5. Послідовна (елементи модуля використовуються в певному порядку).
  6. Функціональна (елементи модуля виконують єдину задачу).
  7. На рівні даних (модуль реалізує АТД) – найприйнятніший варіант.

 

Правило Деметера

 

Правило визначає, що можна і що не можна використовувати в середині класів та методів з метою підвищення зв’язності і зменшення зачеплення.

Припустимо, що слід розробити клас C із методом M.

I. Правило Деметера для класів:

В методі M класу С повинні використовувати виключно методи:

  1. Самого класу С;
  2. Класів, до яких належать аргументи метода M.
  3. Класів глобальних та локальних змінних.

Варіант 1 є прийнятнішим за варіант 2.

 

II. Правило Деметера для об’єктів:

Всередині методу можна звертатись до об’єктів, які є:

1) аргументами цього метода;

2) одержувачами метода;

3) глобальними змінними;

4) локальними змінними.

 

Приклад

 

procedure TMyClass.Draw;

begin

Form1.Canvas.LineTo (10, 100); //не зовсім коректно;

end;

 

procedure TMyClass.Draw (MyCanvas: TCanvas);

begin

MyCanvas.LineTo (10, 100); // коректно (варіант 1);

end;

 

Тема 7. Опрацювання виняткових ситуацій

Основні поняття

Виняткова ситуація

Оператор Try

 

Розглянемо приклад:

 

Program Text;

Var a, b : integer;

Begin

Readln (a, b); // можливе некоректне введення

Writeln(a div b); // можливе ділення на 0

End.

 

Виняткова ситуація (вийняток) – це об’єкт класу Exception або одного з його нащадків, який описує певну нестандартну ситуацію, яка виникла в програмі. Наприклад, ділення на 0, переповнення, спроба відкрити неіснуючий файл.

Мета опрацювання виняткових ситуацій – зробити програму стійкішою, внаслідок виявлення та опрацювання помилок у простий та стандартний спосіб.

Якщо програма не перехоплює виняткову ситуацію, вона опрацьовується методом HandleException класу TApplication.

Стандартна реакція – видача повідомлення (в текстове вікно), знищення об’єкту для вийняттку, завершення роботи поточного блоку програми.

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

 

Клас Exception

1) Від класу TObject успадковані:

- Конструктор;

- Метод ClassName (можна визначити клас для ситуації), наприклад: EZeroDivide, EOverflow, EConvertError, EInOutError.

2) 2 властивості класу Exception

- Message – рядок з повідомленням;

- HelpContext – номер розділу конкретної довідки (по F1) у файлі допомоги.

3) 8 конструкторів

Create

Create Fmt

Create Res

Create ResFmt

Create Help

Create FmtHelp

Create ResHelp

Create ResFmtHelp

 

Fmt= рядок з повідомленням є форматованим;

Res= рядок зчитується з ресурсів;

Help= розділ у файлі допомоги існує.

Для генерування виняткової ситуації використовується ключове слово raise.

 

raise EZeroDivide.Create (‘Ділення на нуль’);

raise EMyError.CreateFmt (‘Задано %d параметрів із %d’,[№1, №2]);

 

Написання захищеного коду

Написання захищеного коду передбачає виявлення та опрацювання виняткових ситуацій і коректне завершення програмних блоків.

Використовуються ключові слова: try, except, finally.

Можливі два варіанти захисту коду:

1) try

// код, що виконується (захищена ділянка)

еxcept

// код, який виконується при виняткових ситуаціях

end;

 

Приклад.

 

{$R+}

procedure TForm1.Button1Click (Sender: TObject);

var A, B: Integer;

C: Shortint;

begin

try

A:= StrToInt (Edit1.Text);

B:= StrToInt (Edit2.Text);

C:= A div B;

except

on EConvertError do

MessageDlg (‘Ви ввели не ціле число’, mtWarning, [mbOK], 0);

on EDivByZero do

MessageDlg (‘Ви ввели нуль’, mtWarning, [mbOK], 0);

on EIntOverflow do

if (A*B)>=0 then C:=127 else C:=-128;

end;

Edit3.Text:=IntToStr(C);

End;

 

2) try

// код, який захищається

finally

// код для усіх випадків (навіть при виняткових ситуаціях)

end;

 

Приклад.

 

procedure TForm1.Button1Click (Sender: TObject);

begin

Screen.Cursor:= crHourglass; // зміна курсору мишки

j:= 0;

try

for i:=1000 downto 1 do

j:= j + j div i; // тут можливі виняткові ситуації

finally

Screen.Cursor:= crDelault; // відновлення курсору мишки

end;

end;

Тема 8. Основи об’єктно-орієнтованого проектування

Основні поняття

ОО проектування

CRC –картки

Діаграма взаємодії

Проектування – створення проектів, які можуть мати декілька складових.

Особливості програмування великих проектів.

Індивідуальний проект:

- код розробляється одним програмістом або невеликою групою;

- окрема людина може зрозуміти всі аспекти проекту, тому основна проблема – написання алгоритму та програми для рішення задачі.

Великий проект - глобальна задача.

- розробляється великою командою програмістів;

- одна група проектує програмну систему, друга – пише коди окремих компонент, третя – об’єднує фрагменти у кінцевий продукт. Немає людини, яка знає все про проект.

Основна проблема – керування проектом і обмін інформацією між групами та всередині груп.

1) Проектування починається з аналізу функції (поведінки) системи, тому що поведінка системи відома раніше від інших властивостей.

2) Уточнення специфікації (визначення, чим буде кінцевий продукт обговорення структури програмної системи і розбиття системи на компоненти).

Компонента в об’єктно-орієнтованому проектуванні – це абстрактна одиниця, яка може виконувати певну роботу (мати певні обов’язки).

Компоненти можуть бути функціями, процедурами, класами, модулями.

Вимоги до компоненти:

1) Повинна мати невеликий набір чітко визначених обов’язків;

2) Повинна взаємодіяти з іншими компонентами з іншими компонентами настільки слабо, наскільки це можливо.

Обов’язки можна записати на карточки типу CRC-картка.

Картки розподіляються між учасниками проекту, при цьому будь-яка дія, яка може відбутися в системі, приписується певній компоненті як обов’язок.

Приклад: програмна система простий текстовий редактор.

Обов’язки:

1) Вивести вікно для тексту;

2) Ввести новий текст з клавіатури;

3) Виправити текст у вікні;

4) Зберегти введений текст;

5) Відкрити збережений текст;

6) Обмін з іншими програмами через ClipBoard;

7) Інші обов’язки: форматування, пошук та заміна, підтримка різних шрифтів, перевірка орфографії.

Діаграми взаємодії компонент

По горизонтальній осі відкладаються назви компонент.

По вертикальній – час роботи програми (згори донизу).

Взаємодія позначається стрічками (від ініціатора до об’єкта взаємодії).

Готовність компонент до змін

Компоненти мають бути реалізовані готовими до змін:

1. будь-які зміни повинні зачіпати якнайменше компонент

2. потрібно передбачити імовірні джерела змін (інтерфейс, формати даних (вхідних та вихідних))

3. зменшити залежність програмного забезпечення від апаратури

4. зменшити зв’язки між фрагментами програми, а також ведення проектної документації про процес розробки і мотиви прийнятих рішень.

Документація включає власне проектну документацію – протокол основних прийнятих рішень, загальний опис програмної системи і далі теж саме, але на рівні програмних компонент.

Документація також включає посібник користувача (User Manual), який включає опис взаємодії системи з точки зору користувача.

Компоненти можуть бути реалізовані у вигляді функцій (поведінка) або класів (поведінка + стан об’єкта ), при цьому кожному обов’язку відповідає назва функції або методу класу.

Вибір імен:

1) імена, які можна вимовити вголос;

2) використовувати великі літери на початку слів або знак _;

3) уважно перевіряти скорочення;

4) уникати багатозначності у назвах;

5) не використовувати цифри;

6) для функцій, які використовуються не часто, давати унікальні імена для уникнення конфліктів.

Назви функцій записуються на звороті CRC-картки.

Наступні кроки:

Вибір представлення даних – для кожної з компонент свої структури даних. Надалі поведінка реалізується як алгоритм і запис на певній мові програмування (мовах), документується та перевіряється коректність роботи при коректних вхідних даних.

Інтегрування компонент.

Для нереалізованих компонент ставляться “заглушки” (англ. stub). Тестуються окремі блоки та система в цілому.

Надалі можливий етап супроводу та розвитку:

- “латки” для помилок (англ. pаtch);

- нові версії (через зміну вимог або апаратного забезпечення);

- виготовлення або покращення документації.

Література:

  1. Архангельский А.Я. Delphi 6. Справочник. М.: Бином, 2001.
  2. Бадд Т. Объектно-ориентированное программирование в действии. СПб.: Питер, 1997.
  3. Буч Г. Объектно-ориентированный анализ и проектирование с примерами приложений на С++. М., Бином, СПб., Невский диалект, 2001.
  4. Кенту М. “Delphi 7 для профессионалов”, СПб, Питер, 2004.
  5. С. Тейксейра, К. Пачеко “Borland Delphi 6. Руководство разработчика”, М., Вильямс, 2002.
  6. Meyer B. Object-Oriented Software Construction. London: Prentice Hall International, 1997.

 


ОБ’ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ

КОНСПЕКТ ЛЕКЦІЙ

для студентів базового рівня за напрямками

“Видавничо-поліграфічна справа” (шифр – 6.09.27)

та “Комп’ютерні науки” (шифр – 6.08.04).

 

Укладачі:

Іванна Дронюк

Юрій Цимбал

 

Тиражування здійснене на кафедрі АСУ Маційовським В.Т.

 

 

Формат 60x84 1/16. Друк на різографі. Тираж 30 прим.

Умовн. друк. арк. 2,0