
- •Передмова
- •Розділ 1 об'єктний підхід у програмуванні
- •1.1.Причини виникнення ооп
- •1.1.1.Складність об'єкта дослідження
- •1.1.2.Складність процесу розробки програмного забезпечення
- •1.1.3.Складність опису окремих елементів
- •1.2.Парадигма ооп
- •1.3.Історія розвитку ооп
- •Розділ 2 об'єкти й класи: інкапсуляція
- •2.1.Структура об'єкта й класу
- •2.2.Особливості опису класів у мовах ооп
- •2.2.1.Опис класів в SmallTalk
- •2.2.3.Опис класів в Delphi
- •2.2.4.Опис класів в Java
- •2.3.Поля даних та їх ініціалізація
- •2.3.1.Визначення полів даних в SmallTalk
- •2.3.3.Визначення полів даних в Delphi
- •2.3.4.Визначення змінних в Java
- •2.4.Доступ до даних
- •2.4.1.Доступ до даних в SmallTalk
- •2.4.3.Доступ до даних в Delphi
- •2.4.4.Доступ до даних в Java
- •2.5.Спеціальні змінні
- •2.5.1.Спеціальні змінні в SmallTalk
- •2.5.3.Спеціальні змінні в Java
- •2.5.4.Спеціальні змінні в Delphi
- •2.6.Посилання
- •2.6.1.Визначення посилань в SmallTalk, Delphi і Java
- •2.7.Методи
- •2.7.1.Загальна схема визначення методу
- •2.7.2.Визначення методів в SmallTalk
- •2.7.4.Визначення методів в Delphi
- •2.7.5.Визначення методів в Java
- •2.8."Дружні" методи
- •2.8.2.Аналог дружніх функцій в Delphi
- •2.9.Конструктори й деструктори
- •2.9.1.Конструктори й деструктори в SmallTalk
- •2.9.3.Конструктори й деструктори в Delphi
- •2.9.4.Конструктори й деструктори в Java
- •2.10.Властивості
- •2.10.1.Властивості в Delphi
- •2.10.2.Властивості в Java
- •2.12.Абстрактні методи
- •Розділ 3 успадкування
- •3.1.Форми успадкування
- •3.2.Успадкування в SmallTalk
- •3.3.1.Віртуальне успадкування
- •3.3.2.Правило сумісності типів
- •3.3.3.Використання конструкторів і деструкторів при успадкуванні
- •3.4.Успадкування в Delphi
- •3.4.1.Ієрархія класів в Delphi
- •3.4.2.Створення нових компонентів
- •3.5.Успадкування в Java
- •3.5.1.Використання ключового слова super
- •3.5.2.Клас Object
- •Розділ 4 поліморфізм
- •4.1.Віртуальні методи
- •4.2.1.Механізм пізнього зв'язування
- •4.2.2.Таблиця віртуальних методів
- •4.3.Поліморфізм в Delphi
- •4.3.1.Заміщення віртуальних і динамічних методів
- •4.3.2.Приведення типів
- •4.4.Поліморфізм в Java
- •4.5.Поліморфізм в SmallTalk
- •5.1.Потокові класи
- •5.1.1.Ієрархія потокових класів
- •5.1.2.Форматоване введення/ виведення
- •5.1.3.Маніпулятори
- •5.1.4.Введення/виведення у файл
- •5.2.Контейнерні класи
- •5.2.1.Ітератори
- •5.2.2.Визначення контейнерних класів
- •5.2.3.Стандартні контейнерні класи
- •5.3.1.Параметиізовані класи (шаблони)
- •5.3.2.Ітератори stl
- •5.3.3.Узагальнені алгоритми
- •Література
- •Додатки лабораторна робота №1 об'єкти й повідомлення в smalltalk
- •Лабораторна робота №2 класи й методи в smalltalk
- •Листинг 3.1
- •Листинг 3.2
- •Листинг 3.3
- •Лабораторна робота 5 компоненти в delphi
- •Лабораторна робота 6 меню й вікна в delphi
- •Лабораторна робота 7 розробка меню в java
- •Лабораторна робота 8 робота з подіями в java
Лабораторна робота 5 компоненти в delphi
Ключ до розуміння того, як використовуються класи в Delphi, знаходиться в розумінні роботи компонента. Компоненти є об'єктами класу й мають всі його можливості.
Палітру компонентів Delphi можна розділити на 2 групи: візуальні компоненти – ті, які відображаються на екрані, коли програма виконується, і невізуальні компоненти, які не відображаються під час виконання програми. Форми, мітки, кнопки - явні приклади візуальних компонентів. Невізуальні компоненти містять у собі таймери, меню, загальні вікна діалогу й елементи управління доступом до даних.
Кожна програма в Delphi складається принаймні з одного компонента. Форма (Form) – “головне вікно” традиційних додатків Windows. Імовірно, що існує більш ніж одне вікно форми в додатку. Вікно форми може викликати й відображати іншу форму.
Властивості компонентів
Управляти роботою компонентів можна за допомогою їхніх властивостей, які інкапсулюють у собі поля даних і методи (оброблювачі подій). Коли створюється нова форма, Delphi ініціалізує її розмірами за замовчуванням і встановлює такі властивості, щоб відобразити стандартне вікно Windows. Властивості можуть бути змінені у вікні Інспектора Об'єктів. На рис. 5.1 показаний вид Інспектора Об'єктів для компонента Form.
Властивості, які видні у вікні Інспектора об'єктів для конкретного компонента - це властивості періоду проектування. Значення, які ви для них встановлюєте - це значення, які будуть використовуватися, коли цей компонент буде відображений у перший раз. Ці властивості можуть бути змінені під час виконання програми. Є також динамічні властивості, які не відображені Інспектором об'єктів і можуть управлятися тільки під час виконання програми, а також властивості тільки-для-читання, які можуть бути прочитані, але не змінені.
Рис. 5.1. Властивості компонента Form
Успадкування батьківських властивостей
Існують різні властивості, які Delphi передає з форми (батьківського елемента керування) нащадкам. Більшість візуальних компонентів мають властивості, які елемент керування успадкував від батьківських властивостей. Ці властивості ParentCtl3D, ParentColor і ParentFont. Вони приймають за замовчуванням значення True, що змушує компонент успадковувати властивості форми.
Якщо для конкретного компонента встановити одну із цих властивостей в False, то Delphi буде використовувати при відображенні компонента значення властивості компонента, а не батьківського елемента. Щоб змінити шрифт, щоб намалювати кнопку з текстом, необхідно просто змінити властивість Font кнопки, і властивість ParentFont буде змінене на False. Аналогічно буде, якщо змінити значення Color або Ctl3D для компонентів, що відповідають властивості ParentCtr3D і ParentColor приймають значення False. Якщо змінити одну з властивостей ParentХХХ компонента з False в True, тоді Delphi автоматично скопіює в компонент із батьківського елемента керування відповідний шрифт, цвіт або 3-D, стираючи будь-яку зміну, що ви, можливо зробили в цих властивостях.
Створимо програму, що дозволить змінювати цвіт вікон і шрифтів. Крім того, компонент ColorGrid (таблиця кольорів), дозволить вибирати колір, також форма буде мати мітку й контрольне вікно (check box). Мітка успадковує властивості форми, а контрольне вікно буде успадковувати властивості форми, коли буде позначена.
Виберіть File/New Project з головного меню Delphi, і почніть зі свіжої форми. В Інспекторі Об'єктів зменіть властивість Заголовок (Caption) форми на Parent Properties Example (приклад батьківських властивостей). Виберіть із палітри компонентів компонент Мітка (Label) і поставте його у верхньому лівому куті форми. Як тільки встановите мітку можна використати Інспектор Об'єктів, щоб змінити властивість Заголовок мітки з Label1 на будь-який текст, що ви захочете, наприклад, «This label always inherits the form's colors».
Далі виберіть компонент контрольне вікно (білий квадрат з “х” у ньому) і помістіть його у форму. Переконайтеся, що новий компонент контрольного вікна не перекриває вже існуючу мітку. В Інспекторі Об'єктів зменіть властивості Заголовок (Caption) контрольного вікна на “ParentColor” (батьківський цвіт) і замініть властивість Checked (Позначити) на True. Останній компонент, який ми збираємося додати – це ColorGrid. Цей компонент розташований на сторінці Samples палітри компонентів. Для того, щоб встановити його, спочатку клацніть на закладці Samples у палітрі компонентів, потім використайте вспливаючі пояснення для пошуку компонента ColorGrid (це таблиця з 16 комірками різнихкольорів). Клацніть на компоненті ColorGrid, потім клацніть на формі, щоб помістити компонент у формі. Перед тим як продовжити, ви можете клацнути на закладці Samples у палітрі компонентів для того, щоб знову повернутися до відображення стандартних компонентів.
В Інспекторі Об'єктів встановіть властивість BackgroundIndex для ColorGrid в “5” і переконайтеся, що властивість ForegroundIndex встановлена в “0”. Ці установки відповідають пурпурному цвіту із чорним текстом.
При бажанні ви можете розташувати елементи керування так, щоб форма виглядала краще. Одне з можливих розміщень показане на рис. 5.2.
Рис. 5.2. Форма приклада успадкування властивостей
Далі необхідно написати такий код на Object Pascal:
Встановлює властивості форми Color і Font при запуску програми.
Змінює властивості форми Color і Font.
Змінює властивості ParentColor і ParentFont для контрольного вікна.
Установка властивостей компонента при запуску
Коли форма завантажується в перший раз, Delphi викликає процедуру обробки події форми OnCreate, так що форма може проініціалізувати свої значення для запуску. Оскільки ми хочемо змінити колір форми й тексту так, щоб відбити початкові параметри ColorGrid, ми повинні переконатися, що при запуску програми вони встановлюються правильно.
Для того, щоб додати оброблювач події OnCreate, клацніть на порожньому місці у формі, щоб переконається, що Інспектор Об'єктів відображає властивості форми. Потім клацніть на закладці Події (Events), щоб вибрати сторінку Подій, і зробіть подвійне клацання на області значення праворуч від події OnCreate. Delphi покаже вікно Unit, і символ курсору буде розташований для вас так, щоб ввести код події між begin і end. Введіть наступні два рядки коду з поточної позиції курсору:
Color := ColorGrid1.BackgroundColor ;
Font.Color := ColorGrid1.ForegroundColor ;
Перший рядок встановлює колір форми (властивість Color) у колір, що відповідає властивості BackgroundIndex для ColorGrid, а другий рядок установлює підвластивість Color властивості Font форми у колір, що відповідає властивості ForegroundIndex для ColorGrid.
Коли ви переглянете список властивостей Інспектора Об'єктів для компонента ColorGrid, зверніть увагу, що там є BackgroundIndex і ForegroundIndex, але немає BackgroundColor або ForegroundColor. Справа в тому, що, ми не можемо написати такий код
Color := ColorGrid1.BackgroundIndex ;
для того, щоб змінити колір, оскільки Windows визначає колір, змішуючи значення інтенсивності червоного (red), зеленого (green) й синього (blue) коляпів (RGB ). Компонент ColorGrid запитує в Windows його стандартну системну палітру кольорів і відображає ці кольори у своїй таблиці з 16 комірками. Властивості BackgroundIndex і ForegroundIndex – індекси в таблиці, з якої ColorGrid завантажує значення RGB для стандартних кольорів Windows. BackgroundColor і ForegroundColor – динамічні (часу виконання) властивості, які повертають фактичні значення RGB, проіндексовані властивостями BackgroundIndex і ForegroundIndex. Зверніть увагу, що BackgroundColor і ForegroundColor властивості тільки-для читання. Якщо ви напишете:
ColorGrid1. BackgroundColor :=0 ;
в одному з оброблювачів подій, то, коли ви спробуєте скомпілювати проект, Delphi видасть повідомлення про помилку: “Error 174, Cannot assign to a read-only property”.
Зміна властивостей форми Color і Font
Наступна частина коду змінює кольори форми, коли ви змінюєте кольори в ColorGrid. Необхідно створити оброблювач події OnChange для компонента ColorGrid.
Коли вікно Form обране, клацніть на компоненті ColorGrid так, щоб ми могли змінити його властивості. В Інспекторі Об'єктів виберіть сторінку Events (Події) і зробіть подвійне клацання на області значення праворуч від події OnChange. Буде знову відображене вікно Unit з курсором там, де ви можете ввести код події OnChange для ColorGrid. Введіть наступні два рядки коду:
Color := ColorGrid1.BackgroundColor ;
Font.Color := ColorGrid1.ForegroundColor ;
Керування контрольним вікном
Стандартне контрольне вікно Windows може бути в одному із двох станів: позначене або не позначено. Цей елемент керування звичайно використовується для того, щоб установити програмну опцію True або False. Delphi реалізує для контрольного вікна стандартні функціональні можливості Windows. У нашій програмі стан компонента контрольного вікна визначає, чи буде він використовувати властивості Color і Font для Form. Якщо контрольне вікно позначене (Checked - установлене в True), то контрольне вікно буде відображатися з використанням кольорів форми. Якщо ні (властивість Checked = False), то контрольне вікно відображається з використанням його власних колярів.
Ми можемо додати цю поведінку до елемента керування контрольного вікна, так змінивши властивості ParentColor і ParentFont, щоб вони відповідали стану контрольного вікна. Delphi викликає оброблювач події OnClick для контрольного вікна щораз, коли на контрольному вікні робиться клацання мишею. Усе, що ми повинні зробити, це додати оброблювач події OnClick.
При відкритій формі клацніть на компоненті контрольного вікна. Переконайтеся, що сторінка Events (Події) в Інспекторі Об'єктів відображається, і виконайте подвійне клацання на полі значення праворуч від оброблювача події OnClick. Коли з'явиться вікно Unit, введіть наступний код:
CheckBox1.ParentColor := CheckBox1.Checked ;
CheckBox1.ParentFont := CheckBox1.Checked ;
Збереження й виконання програми
Перед тим, як ви протестуєте програму, вам належить зберегти результати вашої роботи. Виберіть із головного меню Delphi File/Save Project і в рядку імені введіть PARNTFRM.PAS, а імені проекту – PARENT.DPR. Як тільки ви дали імена двом файлам, ви можете зберегти весь проект, натискаючи на кнопку Save Project на панелі інструментальних засобів.
Як тільки ви зберегли вашу роботу, ви можете скомпілювати й запустити програму вибираючи в меню Run/Run, або натискаючи “гарячу клавішу” F9. Якщо ви одержуєте помилку компілятора, переконаєтеся, що ви ввели всі рядки точно так, як показано вище по тексту. Ви можете зробити зміни, вибираючи вікно Unit і редагуючи код, як у будь-якому звичайному текстовому редакторі. Обов'язково знову збережіть вашу роботу перед тим, як спробуєте запустити програму.
Коли ви запустите програму, фон форми буде пурпурним, а текст буде чорним. Для того, щоб змінити колір символів, встановіть курсор миші на потрібному кольорі в компоненті ColorGrid і клацніть лівою кнопкою миші. Для того, щоб змінити колір фону, встановіть мишу на потрібний колір і клацніть правою кнопкою миші. Якщо ви не хочете, щоб компонент контрольного вікна використовував ті ж кольори, що й форма, клацніть на контрольному вікні так, щоб він став немаркованим (це значить що в рамці ні “х”). Це не відіб'ється відразу на кольорах контрольного вікна, тому що властивості Color і Font вже встановлені так, щоб відображати батьківські кольори. Якщо ви зараз зміните батьківські кольори, клацаючи в ColorGrid, цвіту контрольного вікна не зміняться. Зверніть увагу, що колір компонента Мітка (Label) завжди відображає установку форми, оскільки властивості ParentColor і ParentFont для мітки встановлені в True. Якщо ви знову клацнете на контрольному вікні, його кольори відразу зміняться так, щоб відображати колір Форми.
Невізуальні компоненти
Компонент ТАЙМЕР (Timer) являє яскравий приклад використання невізуальних компонентів. Він являє собою простий хронометр, що працює у фоновому режимі. Через регулярні інтервали "прокидається" і посилає повідомлення програмі, викликаючи оброблювач події OnTimer. Ви можете включати й виключати таймер за допомогою зміни його властивості Enabled, ви можете регулювати швидкість таймера, змінюючи його властивість Interval.
Установка інтервалу
Властивість таймера Interval визначає кількість мілісекунд між подіями OnTimer (тиками). Установка інтервалу в 0 те ж саме, що й закінчення роботи таймера. Максимальне значення Interval дорівнює 32767, що дасть у результаті 1 тик таймера в кожні 32767 сек.
Хоча таймер Delphi здатний генерувати 1000 тиків у секунду, варто бути обережним при програмуванні відгуку програми на тик таймера. Якщо ваша програма витрачає на обробку тику таймера більше часу, ви будете пропускати подію OnTimer. Майте також на увазі, що й інші Windows-програми також можуть впливати на генерацію тиків таймера. Якщо у вас у фоновому режимі працює додаток, що споживає час центрального процесора, тоді досить сумнівно, що ваша програма одержить всі тики таймера, якщо Interval приймається за 100 тиків у сек.
Створимо програму, що реалізує секундомір. Ця програма буде відображати Загальний Час (Total Time) і Час Інтервалу (Lap Time), а також три кнопки: Start/Stop, Інтервал (Lap) і Reset. Остаточна форма показана на рис. 5.3.
Рис. 5.3. Остаточна форма секундоміра (Stopwatch)
Розміщення компонентів.
Почніть із нової форми, вибираючи з головного меню File/New Project. Змініть властивість Caption форми на Stopwatch (секундомір). Клацніть клавішею миші на компоненті Label у палітрі компонентів і помістіть мітку у вашу форму. В Інспекторі об'єктів змініть властивість Caption мітки на Total Time (загальний час). Створіть іншу мітку й змініть її Caption на - Lap Time (час інтервалу). Розмістите ці мітки як показано на малюнку 5.3.
Хоча два рядки, що відображають час, будуть схожі на компоненти редагування (Edit), насправді вони Memo. Причина, по якій використовується компонент Memo, полягає в тому, що в нього є властивість Alignment (вирівнювання), що дозволяє відображати текст вирівняним вправо. Щоб додати рядок, що відображає Total Time, виберіть компонент Memo з палітри компонентів і помістіть у вашу форму праворуч від мітки Total Time. В інспекторі об'єктів встановить властивості компонента, як показано в таблиці 5.1.
Таблиця 5.1
Зміна властивостей для відображення Total Time
-
Властивість
Змінити на
BorderIcons.Maximize
False
BorderStyle
bsSingle
Enabled
False
Name
TotalTime
ReadOnly
True
TabStop
False
Text
0.0
Оскільки відображення Lap Time буде мати ті ж властивості, що й відображення Total Time (за винятком властивості Name), ви можете заощадити час, використовуючи засоби копіювання й вставки компонентів Delphi.
Запам'ятовування часу
Виберіть компонент Timer на сторінці System палітри компонентів і помістіть його у вашу форму праворуч від двох Memo відображення часу. В інспекторі об'єктів встановіть його властивість Enabled в True і встановіть Interval в 100, що дасть вам 10 тиків у секунду. Потім перейдіть на сторінку Events в Інспекторі об'єктів і виконайте подвійне клацання мишею праворуч від OnTimer, щоб створити оброблювач події для тиків таймера. Відредагуйте процедуру Timer1Timer у вікні Unit у такий спосіб:
procedure TForm1.Timer1Timer(Sender: TObject) ;
Var
s : String ;
Seconds : Real ;
begin
TickCounter := TickCounter + 1 ;
Seconds := TickCounter / 10 ;
Str (Seconds:10:1, s) ;
TotalTime.Text := s ;
end ;
Перейдіть на початок файлу у вікні Unit і знайдіть private-секцію визначення класу TForm1. Включіть нижче вказаний опис змінних відразу після коментарю "Private declarations":
TickCounter: Longint ;
LapCounter: Longint ;
Перша змінна, TickCounter, зберігає підраховані тики. Оброблювач події OnTimer повинен коректувати цю змінну по кожному тику таймера. Друга змінна, LapCounter, буде використовуватися для того, щоб зберігати обчислений минулий інтервал часу, коли кнопка Lap (інтервал) буде натиснута (її ми створимо пізніше).
Оброблювач події OnTimer – процедура, що викликається щораз, коли таймер генерує тик. Перший рядок коду збільшує змінну TickCounter на 1, вказуючи, що пройшов тик таймера. Другий рядок перетворює кількість тиків (десяті частки секунди) у секунди шляхом ділення TickCounter на 10. Результат зберігається в змінній Seconds. Третій рядок коду оброблювача події OnTimer використовує функцію Str() для того, щоб перетворити значення, що зберігається в змінній Seconds, у відформатований рядок, що зберігається в локально оголошеному рядку s. Останній рядок коду змінює властивість Text компонента Memo для TotalTime, встановлюючи його так, щоб він відображав новий часовий відлік.
Ініціалізація лічильника тиків
Перед створенням форми необхідно проініціалізувати змінні TickCounter і LapCounter. Коли створюється форма, відбувається подія OnCreate. Щоб додати оброблювач події OnCreate, виберіть компонент Form клацніть мишею на порожньому місці в області форми, а на сторінці Events в Інспекторі Об'єктів виконайте подвійне клацаньє мишею на OnCreate. Далі введіть наступний код:
TickCounter := 0;
LapCounter := 0;
Запуск і зупинка таймера
Виберіть компонент Button з палітри компонентів і помістіть на форму три кнопки нижче рядків, що відображають час. Використайте інструментальні засоби вирівнювання й зміни розмірів так, щоб установити кнопки.
Клацніть мишею на першу кнопку, позначену Button1, після чого використайте Інспектор Об'єктів, щоб змінити її властивості Name на StartBtn, а її властивість Caption на &Start. Потім зі сторінки Events виберіть подію OnClick і відредагуйте код так, як показано нижче:
procedure TForm1.StartBtnClick(Sender: TObject);
begin
If Timer1.Enabled Then begin
Timer1.Enabled := False;
StartBtn.Caption := '&Start';
end
else begin
Timer1.Enabled := True;
StartBtn.Caption := '&Stop';
end;
end;
Оброблювач події моделює кнопку Start/Stop на секундомірі, включаючи й виключаючи таймер. Якщо секундомір запущений (властивість таймера Enabled = True), то оброблювач події виключає таймер і змінює Caption кнопки на Start. Якщо секундомір не працює, тоді цей код запускає таймер, встановлюючи його властивість Enabled в True і змінює Caption кнопки на Stop.
Підрахунок інтервалів
Для того, щоб підраховувати інтервали часу, ми повинні знати поточний підрахований час, а також час кінця попереднього інтервалу. Кожний інтервал часу являє собою різницю між поточним, минулим часом і часом завершення попереднього інтервалу. Отже, наш таймер повинен стежити за часом, що пройшов від кінця попереднього інтервалу, так, щоб він міг обчислити час поточного інтервалу.
Для того, щоб додати до секундоміра цю можливість, клацніть мишею на другій кнопці, що ви помістили у форму, змініть її властивість Name на LapBtn, і змініть її властивість Caption на &Lap. Потім створіть оброблювач події OnClick для цієї кнопки й відредагуйте його код:
procedure TForm1.LapBtnClick(Sender: TObject);
var
s : String;
Temp : Longint;
begin
Temp := TickCounter - LapCounter;
LapCounter := TickCounter;
Str ((Temp/10):0:1, s);
LapTime.Text := s;
end;
Перший рядок цього коду обчислює час поточного інтервалу, віднімаючи кількість тиків наприкінці попереднього інтервалу з поточної кількості тиків. Це значення зберігається в тимчасовий змінній Temp. Потім ми коректуємо змінну LapCounter, щоб вона містила таку кількість тиків до кінця цього інтервалу, щоб ми могли обчислювати час наступного інтервалу. Нарешті, ми використаємо Str, щоб відформувати час інтервалу в Temp, потім встановлюємо властивість Text для LapTimer для того, щоб відбити час нового інтервалу.
Скидання таймера
Скидання таймера результат установки змінних TickCounter і LapCounter в 0, і установки властивостей Text, що відображають час, назад в 0. Код, що це робить, дуже простий. Змініть властивість Name третьої кнопки на ResetBtn, її властивість Caption на &Reset, після чого створіть оброблювач події в такий спосіб:
procedure TForm1.ResetBtnClick (Sender: Tobject);
begin
TickCounter := 0 ;
LapCounter :=0 ;
LapTime.Text := '0.0' ;
TotalTime.Text := '0.0' ;
end;
Коли ви завершите всі зміни, у вас буде повністю функціональна програма - секундомір. Збережіть вашу роботу й натисніть F9, щоб її скомпілювати й виконати.
Завдання для самостійної роботи:
Змініть форму Stopwatch так, щоб вона змінювала колір через кожні 5 секунд.
Додайте на форму Stopwatch два поля, у яких буде відображатися число виконаних скидань таймера й сумарне значення часу циклів між скиданнями.