Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП_KAZYMYR.doc
Скачиваний:
14
Добавлен:
09.11.2019
Размер:
3.71 Mб
Скачать

Лабораторна робота №2 класи й методи в smalltalk

Кожний об'єкт в SmallTalk є екземпляром якогось класу. Наприклад об’єкти #(1 2 3) і #(sam joe) є екземплярами класу Array(Масив), тоді як 'north' і 'south' є екземплярами класу String (Стрічка). Клас визначає поведінку й параметри подібних об'єктів за допомогою змінних і методів. Змінні зберігають параметри об'єктів, а методи забезпечують здатність об'єктів реагувати на повідомлення, що посилають їм. Всі об'єкти знають, до якого класу вони належать. Виконайте, наприклад, такі вирази:

#(Francesca Jackie Marisa Bree) class

'Rakesh Vijay Charles Daniel Tyler' class

Змінні екземплярів класу

Внутрішні змінні об'єкта, що визначають його властивості, називаються змінними екземпляра (instance variable). Вони існують у всіх об'єктів даного класу. Наприклад, об'єкт класу Fraction має дві змінні екземпляра класу – numerator і denominator (чисельник і знаменник). Для об'єкта, що представляє дріб 1/7, змінна екземпляра класу numerator містить об'єкт 1, а denominator містить об'єкт 7.

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

Виконаєте наступне повідомлення, щоб викликати вікно інспектування:

(1/7 )inspect

Методи екземплярів

Методи – це програми мовою SmallTalk, які визначають поведінку об'єктів. Коли якомусь об'єкту посилається повідомлення, починає працювати відповідний метод, а об'єкт повертає відповідний результат.

Виконайте наступні повідомлення:

(1/7) numerator

Коли повідомлення numerator посилається об’єкту 1/7, SmallTalk виконує метод numerator, визначений у класі Fraction (дріб). Текст методу дуже простий:

numerator

^numerator

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

Розглянемо більш складний приклад:

( 2/3 ) * ( 5/7 )

Посилаючи повідомлення * об’єкту 2/3 з аргументом 5/7, ми змушуємо SmallTalk виконати такий метод:

* aNumber

^(numerator * aNumber numerator) /

(denominator * aNumber denominator)

Перший рядок тут містить ім'я методу * та ім'я аргументу aNumber, що використовується в подальшому як аргумент об'єкта. Метод повертає дріб, у якої чисельник дорівнює добутку чисельників об'єкта й аргумента, а знаменник – добутку знаменників об'єкта й аргумента.

Імена numerator і denominator виступають у даному прикладі як змінні екземпляра класу і як селектори повідомлення. Їх розрізняють по контексту. Зверніть також увагу на те, що значення своїх змінних об'єкту доступні, а до тих же змінних аргументу повідомлення об'єкт одержує доступ тільки через відповідні методи.

Браузер класів

У вікні System Transcript через пункт меню Tools виберіть Browse Classes. Перед Вами з'явиться вікно браузера класів. У верхній лівій панелі вікна відображається список класів, і Ви можете вибрати кожен з них для перегляду. На другій панелі виводяться найменування програм, у яких дані класи використовуються. На третій панелі дається перелік категорій методів класу. Категорія поєднує методи по якій-небудь ознаці. Можна переглянути методи тільки однієї категорії, а можна виділити всі категорії, якщо вибрати відповідний пункт в меню Categories. Для швидкого пошуку потрібного класу необхідно у вікні Classes Browser вибрати в меню Classes пункт Find, ввести назву класу й нажати OK.

Існує дві групи методів – методи екземплярів класу (instance) і методи класу (class). Крім цього методи діляться на приватні (private) і публічні (public).

Знайдіть клас Fraction, виберіть всі категорії, програму CLDT, категорію CLDT-API і приватний метод * на правій панелі. Текст вибраного методу з'явиться на нижній панелі. Ця панель дозволяє редагувати існуючі методи й створювати нові. Прочитайте й проаналізуйте реалізацію методу *. Звірте текст методу з тим, що розглядався раніше. Познайомтеся з іншими методами класу Fraction. Аргументом селектора classVariableNames: є рядок, що задає імена змінних класу, які єдині для всіх екземплярів. Аргументом селектора poolDictionary: є рядок, що задає імена словників (наприклад, словник констант), які використовуються в класі.

Спеціальна змінна self

Тепер розробимо новий метод для класу Fraction:

fraction

"Повертає число мінус його ціла частина."

^self - self truncated

Метод fraction повинен повертати різницю значень об'єкта-одержувача й цілої частини об'єкта-одержувача, тобто дріб меншу за1. В тексті методу ми застосували спеціальну змінну self, значення якої дорівнює значенню об'єкта-одержувача.

Додайте цей метод у клас Fraction, використовуючи наступні операції:

  • клацніть правою кнопкою миші на панелі методів й виберіть функцію New Method Template, або виберіть цю функцію через меню Method;

  • заготовку (template) нового методу, що з’явиться в нижній панелі, змініть відповідно до тексту метода fraction;

  • правою кнопкою миші активізуйте меню нижньої панелі й виберіть функцію Save.

Після цього SmallTalk скомпілює новий метод fraction, і він з'явиться в правому верхньому вікні в переліку методів екземпляра. Перевірте роботу нового методу за допомогою наступних повідомлень:

( 22/7 ) fraction

( 2/3 ) fraction

Методи класу

Класи в SmallTalk також є об'єктами, отже, їм теж можна посилати повідомлення. Такі повідомлення активізують методи класу. Нижче приводяться приклади таких повідомлень, і Ви можете подивитися, як вони працюють:

Array new: 10

Array new

Date today

Time now

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

Друге повідомлення створює масив без елементів.

Два останніх повідомлення створюють екземпляр класу Date (поточна дата ) і екземпляр класу Time ( поточний час ).

Рекурсії

Рекурсія є потужним засобом програмування. Вона використовується тоді, коли алгоритми визначаються через самих себе. У лабораторній роботі №1 Ви використовували повідомлення factorial для обчислення факторіала деякого числа. Давайте розглянемо, як виглядає подібний метод, визначений у класі Integer:

factorial

"Answer an Integer which is the

factorial of the receiver. For example,

6 factorial == 6*5*4*3*2*1.

Fail if the receiver is less than 0."

self > 1 ifTrue: [

^(self - 1) factorial * self].

self < 0 ifTrue: [

ExCLDTValueOutOfRange signal

"Negative value for factorial is invalid"].

^1

У цьому методі об’єкт-одержувач множиться на факторіал числа рівного об’єкту-одержувачу мінус 1. Якщо об’єкт одержувач дорівнює 0 або 1, то повертається 1. Для негативних об’єктів видається повідомлення про помилку.

Виконайте наступний вираз, що посилає повідомлення factorial кожному елементу масиву й повертає новий масив:

#( 0 1 2 3 4 10 15 20 ) collect: [ :n| n factorial ]

Ще одним прикладом, де використовується рекурсія, є обчислення чисел Фібоначчі, які використаються в багатьох застосуваннях. Кожний черговий член послідовності Фібоначчі обчислюється як сума двох попередніх. Два перших члени дорівнюють 1.

Скористайтеся браузером класів для включення цього методу в клас Integer:

fibonacci

"Повертає число Фібоначчі"

^self < 3

ifTrue: [1]

ifFalse: [

(self - 1) fibonacci + (self - 2) fibonacci]

Зверніть увагу, метод fibonacci повертає результат інакше, чим метод factorial. Символ ^ у цьому методі використовується один раз для повернення результату if True: ifFalse: повідомлення.

Перевірте метод fibonacci на наступному виразі:

#(1 2 3 4 5 6 7 10 20 ) collect: [ :m | m fibonacci ]

Ієрархія класів

Багато можливостей SmallTalk пов'язано з ієрархічною організацією його класів. Кожний клас має суперклас і можливо один або кілька підкласів. На вершині ієрархії перебуває клас Object. Класи, що перебувають на більш високих рівнях ієрархії відбивають більш загальні властивості, тоді як класи на нижніх рівнях ієрархії відбивають специфічні особливості об’єктів.

Щоб визначити, до якого класу відноситься об'єкт, йому варто послати повідомлення class. Щоб визначити суперклас для класу, треба скористатися повідомленням superclass, що посилається імені класу.

Подивіться результати наступних повідомлень:

4 class

4 class superclass

4 class superclass superclass

Такий спосіб перегляду ієрархічної організації класів не зовсім зручний. Можливі й інші способи. Викличте меню Tools і виберіть режим Browse classes. У результаті знову буде відкрите вікно Classes Browser, з повною ієрархією класів. Для того, щоб побачити підкласи, служить режим Expand/Collapse, який встановлюється з меню Classes. Коли нас цікавить тільки один якийсь клас і його положення в ієрархії, зручніше за все використати режим Browse Hierarсhy. Скористайтеся цим режимом для перегляду ієрархії класу Boolean.

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

Успадкування методів

Коли об’єкту посилається повідомлення, то SmallTalk намагається знайти визначення відповідного методу в класі об’єкта-одержувача, і якщо знаходить, то виконує його. Якщо ж у даному класі немає визначення відповідного методу, SmallTalk починає його шукати в суперкласі. Пошук може тривати до самого класу Object, а якщо відповідного методу немає й там, то видається повідомлення про помилку.

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

8 min:7

Об'єкт 8 належить до класу SmallInteger у чому легко переконатися за допомогою повідомлення:

8 class

Отже, текст методу, що визначає реакцію об'єкта 8 на повідомлення min:, слід шукати серед методів класу SmallInteger. Відкрийте браузер для цього класу за допомогою пункту Class…меню Tools. У списку ієрархії класів виділіть клас SmallInteger, а в меню Methods/ Visibility виберіть варіант перегляду методів To Root Minus One. При цьому в список методів будуть додані методи всіх суперкласів, за винятком кореневого класу Object. Для методів суперкласів у дужках вказується ім’я відповідного класу (приналежність методу). Як видно із списку методів, метод min визначений у суперкласі Magnitude.

Поліморфізм

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

Як приклад поліморфізму й обробки рекурсивних структур даних розглянемо метод =, визначений в класі ArrayedCollection. Цей метод порівнює екземпляри класу ArrayedCollection і його підкласів з іншими подібними об'єктами, посилаючи повідомлення = елементам обох колекцій. Якщо елемент належить класу ArrayedCollection, метод виконує рекурсивну посилку, використовуючи самого себе. Якщо ж об'єкт належить іншому класу, наприклад, число, то метод використовує нерекурсивну посилку, використовуючи метод = відповідного класу.

= aCollection

"Answer a Boolean which is true when the receiver and the argument

anObject are equivalent, and false otherwise."

self == aCollection ifTrue: [^true].

((self class == aCollection class) and:

[self size = aCollection size]) ifFalse: [^false ].

[:element :index |

element = (aCollection at: index)

ifFalse: [^false ].

] applyWithIndex: self from: 1 to: self size.

^true

В наведеному методі спочатку перевіряється, чи не є це один і той же об'єкт (вираз self == aCollection). Потім перевіряється, чи належать колекції, що розглядаються, до одного і того ж класу, і якщо належать, то чи мають вони однаковий розмір.

Проаналізуйте виконання методу = для рекурсивних структур даних:

#(1 (2 (3))) = #(1 (2 (3)))

#(john smith) = #(john smith)

#(1 'two' 3) = #(1 'two' 3)

Змінні й методи класу

В SmallTalk все є об'єктом, у тому числі й класи. Тому класи теж можуть мати змінні й методи. Але класи входять в іншу ієрархію SmallTalk. Це ієрархія типу клас-метаклас. У рамках цієї ієрархії кожний клас є єдиним екземпляром свого метакласу. Метаклас автоматично створюється при створенні кожного нового класу. Метакласи не мають своїх імен, але доступ до них можливий за допомогою повідомлення class, що посилається імені основного класу, наприклад таким чином:

Integer class Integer class

Для метакласів зберігається ієрархія клас-суперклас, тому у відповідь на повідомлення

Integer class superclass

одержимо відповідь

Number class.

Класом всіх метакласів є спеціальний клас MetaClass, що відбиває найбільш загальні властивості класів:

Integer class class Metaclass.

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

Виберіть клас Date, використовуючи Classes Brouser. Потім виберіть панель, позначену як 'class'. Тепер можна подивитися тексти методів класу, у тому числі.

Спеціальна змінна super

Спеціальна змінна super використовується в тих випадках, коли виникає необхідність замість методу даного класу застосувати більш загальний метод з тим же ім'ям, описаний у суперкласі, або просто вказати на те, що необхідний метод перебуває в суперкласі й тим самим прискорити його пошук. Ця змінна представляє такий же об'єкт, як і спеціальна змінна self – об'єкт-одержувач методу (повідомлення), у якому вона з'являється. Різниця в тім, що якщо повідомлення посилається об'єкту super, те починається пошук методу не в класі об'єкта одержувача, а одразу в його суперкласі.

Для приклада проаналізуйте приватний метод класу new класу Process:

new

^super new initialize

Тут спочатку створюється новий процес шляхом виклика метода класу new суперкласа Object. Потім створеному об’єкту класа Process посилається метод екземпляра, а саме метод initialize.

Завдання для самостійної роботи

  1. Використовуючи результати лабораторної роботи №1, в своєму застосуванні, наприклад, MyApplication1, створіть новий клас Flowers, який буде містити метод екземпляру для малювання квітки з ніжкою по заданих координатах початку й кінця ніжки.

  2. Створіть підклас Posy класу Flowers, що буде малювати букет із заданої кількості квіток.

ЛАБОРАТОРНА РОБОТА 3 КЛАСИ Й ОБ'ЄКТИ В C++

Опис класів

Опис класу складається з оголошення елементів класів: полів даних і функцій-членів. У термінології C++ функції-члени – це методи, які обробляють повідомлення, що передаються екземплярам класів, тобто об'єктам.

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

Більшість ключових можливостей опису класу C++ наведено в листингу 3.1. Тут представлений зміст файлу заголовка Fraction.h, що містить опис класу Fraction. Він визначає об'єкти, які є раціональними дробами. За винятком конструкторів, деструктора й двох методів доступу опис цього класу містить тільки прототипи функцій-членів, визначення яких поміщені в окремий файл. Листинг 3.2 містить реалізацію функцій reduced і add, що входять у файл заголовка. В листингу 3.3 представлена частина програми перевірки протоколу класу Fraction. Виклик компілятора (bcc.exe) та запуск програм на виконання (bc.exe) можуть бути проведені безпосередньо з командної строки.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]