Inherited Done;
End;
Підсумок
Об’єкти, як і звичайні змінні, можуть бути динамічними. Новий динамічний об’єкт створюється оператором New, цей оператор має також розширений синтаксис і може водночас зі створенням об’єктної змінної здійснювати її ініціалізацію. Для виявлення помилок конструктора використовується функція HeapFunc такого формату
Function HeapFunc(Size:Word):Integer; Far
Для очищення і видалення динамічних об’єктів Pascal надає розробникам спеціальний тип методу, який називається деструктором. Деструктор об’єднує етап видалення об’єкту з іншими діями чи задачами, необхідними для даного типу об’єкту.
Питання по темі
1. Нехай Т – змінна типу «вказівник на об’єкт». Який запис оператора New буде правильним?
а) New(T)
б) New(^T)
в) New(T^)
2. Як би виглядав розширений синтаксис попереднього оператора за умови, що виклик конструктора Init правильний?
а)New(Init(70,90,120,Т);
б)New(Т, Init(70,90,120);
в)New(Т^, Init(70,90,120);
3. Виклик якої процедури змушує конструктор видалити динамічний екземпляр, що був розміщений при вході в конструктор
а) Fail
б) Delete
в) Refuge
4. Яке ключове слово свідчить про те, що викликається метод предка даного об’єкта?
а) Inherited
б) Ancestor
в) Testament
5. Яка стандартна назва деструктора в TurboPascal?
а) Delete
б) Backup
в) Done
Лекція 9
Тема 2 Об’єктно-орієнтоване програмування в Pascal
Динамічні методи
Внутрішнє представлення об’єктів
Таблиця віртуальних методів
Функції роботи з таблицею віртуальних методів
Таблиця динамічних методів
Виклик статичних методів
Виклик віртуальних методів
Виклик динамічних методів
Виклик конструкторів та деструкторів
Підсумок
Питання по темі
Динамічні методи
В Pascal-і існує додатковий клас методів пізнього зв’язування, які називаються динамічними. Фактично, динамічні методи є підкласом віртуальних методів і відрізняються від них тільки способом виклику на етапі виконання. У всьому іншому динамічний метод можна розглядати як еквівалентний віртуальному.
Опис динамічного методу аналогічний опису віртуального методу, за винятком того, що він повинен включати в себе індекс динамічного методу, який вказується відразу після ключового слова VIRTUAL. Індекс динамічного методу повинен задаватися цілочисельною константою в діапазоні значень від 1 до 65535 і являти собою унікальне значення серед індексів інших динамічних методів, що містяться в об’єктному типі чи його предках. Наприклад
FUNCTION GetName:String;VIRTUAL 5;
Перевизначення динамічного методу повинне точно відповідати порядку, типу та іменам параметрів, а також типу результату функції, якщо метод є функцією. Перевизначення повинне включати в себе директиву VIRTUAL, за якою йде той сам індекс динамічного методу, що і заданий в об’єктному типі предка.
Використання динамічних методів доцільне при створенні довгої ієрархії об’єктів з великою кількістю віртуальних методів. Для цих останніх в ієрархії будуть створюватися дуже довгі таблиці віртуальних методів з вказуванням всіх віртуальних методів предків, хоча перевизначатися може тільки частина з них. Це вимагає значного об’єму використовуваної пам’яті для зберігання VMT.
При використанні динамічних методів створюється альтернативна таблиці віртуальних методів таблиця динамічних методів DMT, в якій вказуються лише ті віртуальні методи, які перевизначаються, що дозволяє зекономити пам’ять.
Внутрішнє представлення об’єктів
Внутрішній формат даних об’єкта нагадує внутрішній формат запису. Поля об’єкту записуються в порядку їх опису як неперервна послідовність змінних. Будь-яке поле, успадковане від батьківського типу, записується перед новими полями, визначеними в дочірньому типі.
Якщо об’єктний тип визначає віртуальні методи, конструктори чи деструктори, то компілятор розміщає в ньому додаткове поле даних. Це 16-бітове поле, що називається полем таблиці віртуальних методів, використовується для запам’ятовування зміщення таблиці віртуальних методів в сегменті даних. Поле таблиці віртуальних методів розміщується безпосередньо після звичайних полів об’єктного типу. Якщо об’єктний тип успадковує віртуальні методи, конструктори чи деструктори, то він успадковує і поле VMT, завдяки чому додаткове поле таблиці віртуальних методів не розміщається.
Ініціалізація поля таблиці віртуальних методів екземпляра об’єкта здійснюється конструктором (чи конструкторами) об’єктного типу. Програма ніколи не ініціалізує поле таблиці віртуальних методів явно і не має до нього доступу.
Наступний приклад ілюструє представлення в сегменті даних об’єктів типів TStudent і TStudent1.
Таблиця віртуальних методів
Кожен об’єктний тип, що містить чи успадковує віртуальні методи, конструктори або деструктори, має таблицю віртуальних методів, в яких запам’ятовується ініцалізована частина сегменту даних програми. Для кожного об’єктного типу (але не для кожного екземпляра) існує тільки одна таблиця віртуальних методів, однак два різні об’єктні типи ніколи не мають спільної таблиці віртуальних методів, незважаючи на те, наскільки вони ідентичні. Таблиці віртуальних методів створюються комп’ютером автоматично і програма ніколи не маніпулює ними безпосередньо. Вказівники на таблиці віртуальних методів теж запам’ятовуються автоматично в екземплярах об’єктних типів за допомогою конструкторів, програма ніколи не працює безпосередньо з цими вказівниками.
Перше слово таблиці віртуальних методів містить розмір екземплярів відповідного об’єктного типу. Ця інформація використовується конструкторами і деструкторами для визначення кількості байтів, які виділяються чи вивільняються при використанні розширеного синтаксису стандартних процедур New і Dispose.
Друге слово таблиці віртуальних методів містить від’ємний розмір екземплярів відповідного об’єктного типу. Ця інформація використовується програмою контролю викликів віртуальних методів для виявлення неініціалізованих об’єктів (екземплярів, для яких не був здійснений виклик конструктора) і для перевірки правильності таблиці віртуальних методів. Якщо дозволений контроль віртуального виклику за допомогою директиви {$R+}, то компілятор генерує виклик підпрограми контролю звертання до таблиці віртуальних методів перед кожним викликом віртуального метода. Ця підпрограма перевіряє нерівність першого слова VMT нулю і рівність суми першого і другого слів нулю. Якщо кожна з перевірок виявила неспівпадіння, то генерується помилка виконання з кодом 210.
Дозвіл перевірок границь діапазонів і перевірок викликів віртуальних методів сповільнює виконання програми і робить розмір EXE-файлів дещо більшим, тому рекомендується використовувати директиву {$R+} тільки під час налагодження і переключати цю директиву в {$R-} у остаточній версії програми.
Третє слово VMT містить зміщення сегменту даних об’єктного типу в таблиці динамічних методів (DMT) чи 0, якщо об’єкт не містить динамічних методів.
Четверте слово VMT резервується і завжди рівне 0.
Нарешті, починаючи зі зміщення 8 таблиці віртуальних методів, йде список 32-розрядних вказівників методів (однин вказівник на кожен віртуальний метод в порядку їх опису). Кожна позиція містить адресу точки входу відповідного віртуального метода.
Наступний приклад демонструє розміщення таблиць віртуальних методів типів TStudent і TStudent1. Кожен маленький прямокутник відповідає одному слову пам’яті, а кожен більший – двом словам пам’яті.
Зверніть увагу на те, як TStudent1 успадковує поліморфний метод ShowName.
Як вже згадувалося, конструктори об’єктних типів містять спеціальний код, що запам’ятовує зміщення таблиці віртуальних методів об’єктного типу та ініціалізованих екземплярів. Наприклад, якщо маємо екземпляр S типу TStudent і екземпляр T типу TStudent1, то виклик S.Init буде автоматично записувати зміщення таблиці віртуальних методів типу TStudent в поле таблиці віртуальних методів екземпляра S, а виклик T.Init – запише зміщення VMT типу TStudent1 в поле VMT екземпляра Т. Ця автоматична ініціалізація є частиною коду входу конструктора, тому, якщо управління передається в початок операторної секції, то поле таблиці віртуальних методів параметра Self теж буде установлено. Таким чином, при необхідності конструктор може виконувати виклик віртуального методу.
Функції роботи з таблицею віртуальних методів
Для безпосередньої роботи з VMT використовуються дві функції:
Function SizeOf(Obj):Word;
Function TypeOf(Obj):Pointer;
Застосована до екземпляра об’єктного типу, що має таблицю віртуальних методів, стандартна функція SizeOf поверне записаний в таблиці віртуальних методів розмір. Таким чином, для об’єктів, що мають таблицю віртуальних методів, функція SizeOf завжди повертає дійсний розмір екземпляра, а не приведений у описі.
Крім того, Pascal надає нову стандартну функцію TypeOf, що повертає вказівник на таблицю віртуальних методів об’єктного типу. Функція TypeOf приймає єдиний параметр, який може бути ідентифікатором об’єктного типу або екземпляром об’єктного типу. В обох випадках результат типу Pointer є вказівником на таблицю віртуальних методів об’єктного типу. TypeOf може застосовуватися лише до об’єктних типів, що мають VMT. Застосування цієї функції до інших типів призведе до помилки.
Функція TypeOf може використовуватися для перевірки фактичного типу екземпляра. Наприклад:
If TypeOf(Self)=TypeOf(TStudent) then…
Таблиця динамічних методів
Таблиця віртуальних методів об’єктного типу містить для кожного описаного в об’єктному типі віртуального методу і його предків 4-байтовий запис. Коли в породжуючих типах (предках) визначається велике число віртуальних методів, в процесі створення дочірніх типів може використовуватися досить великий об’єм пам’яті, особливо якщо цих дочірніх типів є багато. Хоча в дочірніх типах можуть перевизначатися тільки деякі із успадкованих методів, таблиця віртуальних методів кожного дочірнього типу містить вказівник методу для всіх успадкованих віртуальних методів, навіть якщо вони не перевизначалися.
Динамічні методи забезпечують в таких випадках альтернативу. Для таких методів в Pascal-і вводиться новий формат таблиці методів і новий спосіб обробки викликів методів з пізнім зв’язуванням. Замість кодування всіх методів об’єктного типу з пізнім зв’язуванням в таблиці динамічних методів (DMT) кодуються лише ті методи, які були в об’єктному типі перевизначені. Якщо в похідних типах перевизначаються лише деякі з великого числа методів з пізнім зв’язуванням, формат таблиці динамічних методів використовує менший простір, ніж формат таблиці віртуальних методів.
Об’єктний тип має таблицю динамічних методів тільки тоді, коли в ньому вводяться чи перевизначаються, інакше він просто успадковує таблицю динамічних методів свого предка.
Як і у випадку таблиці віртуальних методів, таблиця динамічних методів записується в ініціалізовану частину сегменту даних прикладної програми.
Перше слово таблиці динамічних методів містить зміщення в сегменті даних батьківської таблиці динамічних методів чи 0, якщо батьківська таблиця динамічних методів відсутня.
Друге і третє слова DMT використовуються в кеш-буфері перегляду динамічних методів.
Четверте слово таблиці динамічних методів містить лічильник числа записів таблиці динамічних методів. Безпосередньо після нього йде список слів, кожне з яких містить індекс динамічного методу, а потім список відповідних вказівників методів. Довжина кожного списку задається лічильником числа записів DMT.
Виклик статичних методів
Методи використовують ті самі узгодження про виклики, що й звичайні процедури і функції, за винятком того, що кожен метод має неявний додатковий параметр Self, який відповідає параметру-змінній того ж типу, що і об’єктний тип даного методу. Параметр Self завжди передається останнім і має вигляд 32-розрядного вказівника на екземпляр, з якого викликається метод.
При поверненні метод повинен видалити параметр Self зі стеку так само, як він це робить зі звичайними параметрами. Методи завжди використовують далекий тип виклику незалежно від директиви $F компілятора.
Виклик віртуальних методів
Для виклику віртуального методу компілятор генерує код, який вибирає адресу таблиці віртуальних методів об’єкту і потім викликає метод, використовуючи зв’язану з ним точку входу. Послідовність дій при цьому буде такою: передача параметра Self, встановлення зміщення VMT з поля VMT, виклик відповідного методу через інструкцію Call з врахуванням зміщення.
Виклик динамічних методів
Обробка виклику динамічного методу складніша і вимагає більше часу, ніж виклик віртуального методу. Замість використання інструкції Call для виклику через вказівник методу по статичному зміщенню в таблиці віртуальних методів, таблиця динамічних методів об’єктного типу і таблиця динамічних методів його предка повинні переглядатися в пошуку «найбільш верхнього» входження індексу конкретного динамічного методу, а виклик потім повинен виконуватися через відповідний вказівник методу. Цей процес вимагає використання значно більшого числа інструкцій, які можна записати як вбудовані (INLINE), тому Pascal містить підпрограму обробки викликів, що використовується при виклику динамічного методу.
Спершу обробник вибирає зміщення таблиці динамічних методів з таблиці віртуальних методів. Потім використовується кешований індекс – поле таблиці динамічних методів. Обробник перевіряє, чи є індекс викликаного динамічного методу індексом того динамічного методу, який викликався останнім. Якщо це так, то він негайно передає управління цьому методу, використовуючи непрямий перехід за допомогою вказівника методу, записаного по зміщенню, заданому полем «кешоване зміщення». Якщо динамічний індекс викликаного методу не співпадає з тим, який записаний у кеші, то обробник переглядає власну і батьківські таблиці динамічних методів, використовуючи поле DMT зі зміщенням батьківської DMT, поки не знайде запис з даним індексом динамічного методу. Індекс і зміщення відповідного вказівника методу записуються потім в кешовані поля таблиці динамічних методів, а управління передається методу. Якщо з якихось причин обробник не може знайти запис з даним індексом динамічного методу, він завершує прикладну програму з кодом помилки виконання 210.
Попри використання кешування і добре оптимізованої підпрограми обробки викликів, обробка виклику динамічного методу може вимагати значно більше часу, ніж виклик віртуального методу. Однак у тих випадках, коли самі дії, що виконуються динамічним методом, вимагають багато часу, додатковий простір, що зберігається таблицями динамічних методів може виявитися істотнішим.
Виклик конструкторів та деструкторів
Конструктори і деструктори використовують ті самі узгодження про виклики, що й звичайні методи, за винятком того, що додатковий параметр розміром у слово, що називається параметром VMT, передається через стек безпосередньо перед параметром Self.
Для конструкторів параметр VMT містить зміщення таблиці віртуальних методів для запам’ятовування в полі таблиці віртуальних методів параметра Self, щоб його ініціалізувати.
Більше того, якщо конструктор викликається для розміщення динамічного об’єкту за допомогою розширеного синтаксису стандартної процедури New, через параметр Self передається вказівник Nil.Це змушує конструктор розміщувати новий динамічний об’єкт, адреса якого передається викликаючій програмі через DX:AX при поверненні з конструктора. Якщо конструктор не може розмістити об’єкт, то в DX:AX повертається порожній вказівник NIL.
Нарешті, якщо конструктор викликається з використанням власного ідентифікатора методу (ідентифікатора типу об’єкту, після якого йдуть крапка та ідентифікатор методу), то в параметрі таблиці віртуальних методів передається нульове значення. Це вказує конструктору, що йому не слід ініціалізувати поле Self таблиці віртуальних методів.
Для деструкторів нульове значення параметра таблиці віртуальних методів означає звичайний виклик, а ненульове вказує, що деструктор був викликаний з використанням розширеного синтаксису стандартної процедури Dispose. Це змушує деструктор видалити Self безпосередньо перед поверненням (розмір Self визначається з першого слова Self у VMT).
Підсумок
Динамічні методи є підкласом віртуальних методів і відрізняються від них тільки способом виклику на етапі виконання. Опис динамічного методу аналогічний опису віртуального методу, за винятком того, що він повинен включати в себе індекс динамічного методу, який вказується відразу після ключового слова VIRTUAL.
Якщо об’єкт чи якийсь з його предків містить віртуальні методи, для нього створюється таблиця віртуальних методів (VMT). Для об’єкта, що містить або успадковує динамічні методи, створюється таблиця динамічних методів (DMT)
Обробка виклику динамічного методу може вимагати значно більше часу, ніж виклик віртуального методу. Однак у тих випадках, коли самі дії, що виконуються динамічним методом, вимагають багато часу, додатковий простір, що зберігається таблицями динамічних методів може виявитися істотнішим.
Питання по темі
1. Який із описів динамічного методу не містить синтаксичних помилок
а) FUNCTION GetName:String;VIRTUAL 5;
б) FUNCTION GetName:String;VIRTUAL=5;
в) FUNCTION GetName:String;VIRTUAL:5;
2. Яка функція повертає записаний у таблиці віртуальних методів розмір екземпляру об’єктного типу?
а) SizeOfObject
б) SizeOf
в) Size
3. Що повертає функція TypeOf?
а)вказівник на таблицю віртуальних методів об’єктного типу
б)вказівник на таблицю динамічних методів об’єктного типу
в)розмір таблиці віртуальних методів об’єктного типу
4. Яке з наступних тверджень правильне?
а) в таблиці динамічних методів (DMT) кодуються всі методи типу.
б) в таблиці динамічних методів (DMT) кодуються лише ті методи, які були в об’єктному типі перевизначені.
в) в таблиці динамічних методів (DMT) кодуються всі віртуальні методи типу.
5. Що дає розробнику використання динамічних методів?
а) економію часу
б) можливість безпосереднього доступу до прихованих методів і даних об’єкту
в)економію простору
Лекція 10
Тема 3 Об’єктно-орієнтоване програмування в Delphi
Вступ
Поняття об’єкта в Delphi та операції з ним
Оголошення класу
Властивості
Методи та їх успадковування, поліморфізм
Конструктори і деструктори
Події
Підсумок
Питання по темі
Вступ
Середовище швидкого проектування Delphi містить вбудовану мову, яка до 5-ї версії включно називалася Object Pascal, а у пізніших версіях – Delphi. Вже з назви Object Pascal зрозуміло, що основоположним для Delphi є приницип об’єктного програмування. Справді, Delphi надає в розпорядження розробника дуже значне число об’єктних типів (компонент), які можна використовувати відразу ж, змінюючи деякі їх типи, а можна і перевизначати, створюючи дочірні об’єкти.
Основні засади ООП Delphi успадкувала від Паскалю у різних його варіантах включно з правиласи «хорошого стилю програмування». Кожен тип об’єктів має стандартну назву, яка починається символом «Т», а кожен екземпляр об’єкта цього типу за замовчуванням дістає ту ж назву з відкиданням символа «Т» і додаванням порядкового номеру. Наприклад, тип об’єктів називається TEdit, а екземпляри цього типу дістають назви Edit1, Edit2 і т.д.
Все, раніше нами вивчене про ООП у Паскалі, діятиме і у Delphi, однак Delphi має і багато нових можливостей, які вже дають можливість вважати її повноцінною об’єктно орієнтованою мовою. Крім того, деякі знайомі нам терміни і поняття будуть називатися трохи інакше. Для того, щоб у майбутньому ми могли не просто розробляти візуальний інтерфейс, використовуючи середовище як дитячий конструктор, а створювати повноцінні об’єкти, попередньо опишемо ці нові можливості та відмінності.
Поняття об’єкта в Delphi та операції з ним
Згідно із загальними принципами ООП, об’єкт в Delphi – це сукупність даних і способів роботи з ними. Дані можна розглядати як поля запису. Це характеристики об’єкту. До них може належати його назва, підпис, розміри, колір, видимість чи невидимість, особливості розміщення, шрифт та інше. Як користувач, так і інші об’єкти програми повинні мати можливість читати ті дані об’єкта, які є для них доступними, якось їх обробляти і записувати в об’єкт нові значення. При цьому прямий доступ до даних, як правило, заборонений, згідно з принципом інкапсуляції. З об’єктом бажано працювати тільки за допомогою його власних процедур та функцій які називаються методами. Сукупність даних і методів їх читання та запису називається властивістю. Ці властивості можна встановлювати в процесі проектування або міняти програмно під час виконання прикладної програми. В процесі проектування ми можемо бачити значення деяких цих властивостей за допомогою такої структурної частини Delphi як Інспектор Об’єктів (Object Inspector), можемо змінювати ці значення. Але насправді все спілкування з даними відбувається через методи їх читання і запису. Це відбувається і впроцесі проектування, коли середовище проектування запускає в потрібний момент ці методи, і в процесі виконання прикладної програми, оскільки компілятор Delphi незримо для розробника вставляє у потрібних місцях програми виклики цих методів.
Крім методів, що працюють з окремими даними, в об’єкті є методи, що працюють з усією їх сукупністю і міняють їх структуру. Таким чином, об’єкт є сукупністю властивостей і методів. Але це ще не закінчений опис об’єктів, потрібно ще передбачити взаємодію об’єктів між собою.
Середовищем взаємодії об’єктів є повідомлення, що генеруються в результаті різних подій. Події наступають, насамперед, внаслідок різних дій користувача: клацання мишкою, переміщення курсору мишки, натиску на клавішу клавіатури, відкриття чи закриття певних вікон. Але події можуть наступати і внаслідок роботи самих об’єктів. В кожному об’єкті визначено багато подій, на які він може реагувати. В конкретних екземплярах об’єкта можуть бути визначені обробники якихось із цих подій і вони визначають рекцію екземпляра об’єкта. В значній мірі, проектування у Delphi зводиться до написання цих обробників.
Отож, остаточно об’єкт у Delphi – це сукупність властивостей, методів і подій, на які він може реагувати. Зовнішнє управління об’єктом здійснюється через обробники подій. Ці обробники звертаються до методів та властивостей об’єкта. Початкові значення даних об’єкта можуть задаватися також в процесі проектування установкою різних властивостей. В результаті виконання методів об’єкту можуть генеруватися нові події, що сприймаються іншими об’єктами програми чи користувачем.
В процесі роботи об’єкти можуть створюватися і знищуватися. Таким чином, структура програми є динамічним утворенням, що змінюється в процесі виконання. Основна мета створення і знищення об’єктів – економія ресурсів комп’ютера, насамперед, пам’яті, а також досягнення необхідної гнучкості управління.
З метою організації динамічного розподілу пам’яті у всі об’єкти закладені методи їх створення – конструктори і знищення – деструктори. Конструктори об’єктів спрацьовують при запуску програми, деструктори – при її завершенні. Але нерідко в процесі виконанні динамічно створюються і знищуються нові об’єкти.
Дата добавления: 2015-08-26; просмотров: 814;