
- •Передмова
- •Розділ 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
2.10.2.Властивості в Java
В Java поняття властивостей, аналогічне властивостям в Delphi, пов'язане з поняттям інстроспекціі в JavaBeans. Інтроспекція (від англ. Introspection - самоаналіз, самоспостереження) – це процес аналізу Java-компонента (JavaBean) для визначення його можливостей.
JavaBeans були запропоновані в 1996 році у версії Java 1.1 як засіб реалізації ідеї багаторазового використання коду. Самі по собі Bean-компоненти являють собою програмні будівельні блоки, готові до використання. З них може бути зібрана програмна система, як збирається конструкція з окремих деталей. Властивість – це підмножина стану Bean-компонента. Значення, призначені властивостям, визначають поводження й зовнішній вигляд компонента.
Властивості бувають трьох типів: прості, булеві й індексовані.
Прості властивості мають одиночне значення. Воно може бути визначене за допомогою проектних шаблонів (design patterns), заснованих на угодах про імена:
public T get();
public void set(T arg);
Тут Т позначає тип властивості, а N – його ім'я.
Властивість читання/запису (read/write) використовує обидва ці методи для доступу до своїх значень. Властивість тільки для читання (read-only) використовує тільки метод get, а властивість тільки для запису (write-only) – тільки метод set. Наприклад, три простих властивості для класу Box можуть бути визначені в такий спосіб:
public class Box {
private double depth, height, width;
public double getDepth() {
return depth;}
public void setDepth(double d) {
depth = d;}
public double getHeigth() {
return heigth;}
public void setHeigth(double h) {
heigth = h;}
public double getWidth() {
return width;}
public void setwidth(double w) {
width = w;}
}
Булева властивість має значення true або false і може бути специфікована наступними проектними шаблонами (тут, як і раніше, N позначає ім'я властивості):
public boolean is();
public boolean get();
public void set(boolean value);
Щоб витягти значення властивості використовується перший або другий шаблон. Однак, якщо клас використовує обидва методи, застосовується перший шаблон. Наступний приклад показує визначення класу з однією булевою властивістю:
public class Line {
private boolean dotted = false;
public boolean isDotted(){
return dotted;}
public void setDotted(Boolean dotted){
this.dotted = dotted;}
Індексована властивість складається з безлічі значень. Її шаблон має такий вигляд:
public T get(int index), public void set(int index, T value);
public T[] get();
public void set(T value);
Приклад визначення класу з однією індексованою властивістю типу читання/запис показаний нижче:
public class Chart {
private double data[];
public double getData(int index){
return data[index];}
public void setData(int index, double value){
data[index]= value;}
public double[] getData(){
return data;}
public void setData( double[] valuse){
data= new double [values.length];
System.arraycopy(values, 0, data, 0, values.length);}
}
Іншим способом оголошення властивостей Bean-компонента є використання інтерфейсу BeanInfo, що має кілька методів, включаючи наступні:
PropertyDescriptor [] getPropertyDescriptors();
EventSetDescriptor [] getEventSetDescriptor ();
MethodDescriptor [] ge MethodDescriptor s();
Ці методи повертають масиви об'єктів, які мають інформацію про властивості, події й методи Bean-компонента. Реалізуючи ці методи, розроблювач може точно визначити, яка інформація надається користувачеві, що використовує компонент. Інтерфейс BeanInfo визначений у пакеті java.beans.
2.11.Функції-операції в С++
Це спеціальний вид методів, призначений для перевизначення операцій. Подібні методи є й в SmallTalk, але вони реалізуються як звичайні методи.
У С++ можна перевизначати будь-які операції, за винятком:
<.> - оператор доступу до елементів класу;
<::> - оператор кваліфікації;
<? :> - умовний оператор;
<.*>, < * > - оператори-покажчики на елементи класу.
Останні дві операції дозволяють організувати непряме звернення до елементів класу через покажчик на клас:
class Note {
public:
int c,d;
};
… … … … …
int Note:: * p; // покажчик на цілий елемент класу Note
Note n .* np = new Note
int i,j;
p = & Note :: c;
i = n.*p; // i буде дорівнювати n.c
p = Note :: d;
j = n, *p; // j = = n.d
i = np->*p; // i = = np->d
Функції-операції в С++ передбачені для визначення операцій, що забезпечують інфіксну форму запису дій для абстрактних типів даних:
C3=add(C1,C2); // префіксна форма
C3=C1+C2; // інфіксна форма
Прототип функції-операції має вигляд:
<тип > operator @ (<список параметрів >) {тіло методу},
де @ - символ операції.
Функції-операції повинні бути обов'язково нестатичними, але їх можна визначати як "дружні" функції.
Розглянемо перевизначення операції додавання для комплексних чисел:
"дружня" функція
сlass Complex { double real, image;
public:
Complex(double r, double i) {real = r; imag = i; }
friend Complex operator+ (Complex C1, Complex C2);
…………………};
//реалізація функції
Complex operator+ (Comlex C1, Complex C2)
{ return Complex(C1.real + C2.real, C1.image + C2.image);}
метод класу
//додатково в класі Complex визначимо функцію
Complex operator+ (Complex &C)
{return Complex(C.real + real, C.image + image);}
Виклик оператора:
Complex C1,C2,C3;
C3 = operator+(C1,C2); // дружні функції
C3 = C1.operator+(C2); // функція-метод
Подібним чином можуть бути визначені інші унарні операції, наприклад, інкрементація ++:
сlass X { int i, j ;
рublic:
X operator++(){ i++; j++;}
};
При такому визначенні дану операцію можна використати в такий спосіб:
X a;
a = a++;
Примітка: для унарних операцій компілятори, крім AT&T, не розрізняють префіксну й постфіксну форму запису оператора інкрементації. Тому для збереження сумісності варто використати префіксну форму цього оператора.
Таким чином, унарні й бінарні операції можуть бути перевизначені за допомогою "дружніх" функцій, відповідно, з одним або двома параметрами, або за допомогою методу даного класу без параметрів або c одним параметром, відповідно.
Однак існує ряд операцій, які можуть бути визначені тільки як нестатичні методи: <=>,< ()>, <[]>,<→>.
Розглянемо перевизначення операції <>> - “покажчик класу”. Її параметр повинен бути або об'єктом класу, або посиланням цього типу.
struct A { int *point;
float *pfloat;
……………};
class B {
private :
A *a;
public:
B (void) {a = new A;}
A* operator > (void) {return a;}
…………};
Використання даної операції може бути здійснене за схемою:
void main ()
{ B b;
*(B→point)=24; // b.a>point
*(B→pfloat)=0.7; // b.a>pfloat
…………}
Допускається перевизначення операцій new і delete. Тим самим можна явно здійснювати виклик операцій, що виділяють і звільняють пам'ять (malloc, free), а так само здійснювати додаткові операції для ініціалізації змінних.
При перевизначенні операцій необхідно враховувати наступні загальні правила:
Забороняється одночасно перевизначати операції за допомогою "дружньої" і нестатичної функцій.
Перевизначена операція повинна існувати в мові.
Не можна перевизначати директиви препроцесора (починаються з #)
При перевизначені операцій їхній пріоритет не змінюється.