Здавалка
Главная | Обратная связь

Короткі теоретичні відомості.



· Об’єктно-орієнтована програма як програма, що керується подіями.

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

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

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

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

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

І, навпаки, ми можемо розробляти частини програми, які відповідають за обробку дій користувача, не зв'язуючи ці частини зі створенням потрібних інтерактивних елементів.

· Подія.

Подія з погляду мови С++ – це об'єкт, окремі поля якого характеризують ті чи інші властивості переданої інформації, наприклад:

struct TEvent

{int what

union{

MouseEventType mouse;

KeyDownEvent keyDown;

MessageEvent message;

};

Об'єкт TEvent складається з двох частин. Перша (what) задає тип події, що визначає джерело даної події. Друга задає інформацію, передану з подією. Для різних типів подій зміст інформації різний . Поле what може приймати наступні значення:

evNothing– це порожня подія, яка означає, що нічого робити не треба. Полю what привласнюється значення evNothing, коли подія оброблена яким -небудь об'єктом.

evMouse – подія від “миші”.

Подія від “миші” може мати, наприклад, таку структуру:

struct MouseEventType

{int buttons;

int doubleClick;

TPoint where;

};

де buttons вказує натиснуту клавішу;

doubleClick вказує чи був подвійний щиглик;

where вказує координати “миші”.

evKeyDown -подія від клавіатури.

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

struct KeyDownEvent

{union{int keyCode;

union{char charCode;

char scanCode;

};

};

};

evMessage- подія-повідомлення від об'єкта.

Для події від об'єкта (evMessage) задаються два параметри :

command – код команди, яку необхідно виконати з появою даної події;

infoPtr – передається з подією (повідомлення) інформація.

struct MessageEvent

{int command;

void infoPtr;

};

· Методи обробки подій.

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

GetEvent – формування події;

Execute – реалізує головний цикл обробки подій. Він постійно одержує подію шляхом виклику GetEvent і обробляє їх за допомогою HandleEvent. Цей цикл завершується, коли надійде подія “кінець”.

HandleEvent – оброблювач подій. Обробляє кожну подію потрібним для нього чином. Якщо об'єкт повинен обробляти визначену подію (повідомлення), то його метод HandleEvent повинен розпізнавати цю подію і реагувати на неї належним чином. Подія може розпізнаватися, наприклад, по коду команди (поле command).

ClearEvent – очищає подію, коли вона оброблена, щоб вона не оброблялася далі.

· Оброблювач подій (метод HandleEvent)

Одержавши подію (структуру типу TEvent) оброблювач подій для класу TDerivedClass обробляє його за наступною схемою:

void TDerivedClass::HandleEvent(TEvent& event)

{ //Виклик оброблювача подій базового класу

TBaseClass::handleEvent( event );

if( event.what == evCommand ) // Якщо оброблювач подій базового класу

// подію не обробив

{

switch( event.message.command )

{

case cmCommand1:

// Обробка команди cmCommand1

// Очищення події

СlearEvent( event );

break;

case cmCommand2:

// Обробка команди cmCommand2

СlearEvent( event );

break;

case cmCommandN:

// Обробка команди cmCommand

СlearEvent( event );

break;

default: // подія не оброблена

break;

}

};

}

Оброблювач подій групи спочатку обробляє команди групи, а потім, якщо подія не оброблена, передає його своїм елементам, викликаючи їх оброблювачі подій.

void TGroup::HandleEvent(TEvent& event)

{ if( event.what == evCommand )

{switch( event.message.command )

// обробка подій об'єкта-групи

default: // подія не оброблена групою

//одержати доступ до першого елемента групи

while((event.what != evNothing)!!( /* переглянуті не всі елементи */)

{

//викликати HandleEvent поточного елемента

//перейти до наступного елементу групи

}

break;

}

}

· Метод ClearEvent-очищення події.

ClearEvent очищає подію, привласнюючи полю event.What значення evNothing.

· Головний цикл обробки подій (метод Execute)

Головний цикл обробки подій реалізується в методі Execute головної групи – об'єкта “прикладна програма” за наступною схемою:

int TMyApp::Execute()

{do{endState=0;

GetEvent(event); //одержати подію

HandleEvent(event); //обробити подію

if(event.what!=evNothing) //подія залишилася не обробленою

EventError(event);

}

while(!Valid());

return endState;

}

Метод HandleEvent програми обробляє подію “кінець роботи”, викликаючи метод EndExec. EndExec змінює значення private – змінної EndState. Значення цієї змінної перевіряє метод – функція Valid, що повертає значення true, якщо “кінець роботи”. Такий трохи складний спосіб завершення роботи програми зв'язаний з тим, що в активному стані можуть знаходитися кілька елементів групи. Тоді метод Valid групи, викликаючи методи Valid своїх піделементів, поверне true, якщо усі вони повернуть true. Це гарантує, що програма завершить свою роботу, коли завершать роботу всі її елементи.

Якщо подія залишилася не обробленим, то викликається метод EventError, що у найпростішому випадку може просто видати повідомлення.

· Приклад обробки подій.

Розглянемо найпростіший калькулятор, що сприймає команди в командному рядку. Тут приводиться спрощений варіант. Варіант, за схемою якого варто виконати лабораторну роботу, приведений у Додатку.

Формат команди:

знак параметр

Знаки +, –, *, /, =, ?, q

Параметр – ціле число

Константи-команди:

сonst int evNothing = 0;

сonst int evMessage = 100;

сonst int cmSet = 1; //занести число

сonst int cmGet = 2; //подивитися значення

сonst int cmAdd = 3; //додати

і т.д.

сonst int cmQuit = 101; //вихід

Клас-подія

struct TEvent

{int what

union{

int evNothing;

union{int command;

int a;}

}

}

Об'єкт-калькулятор, що працює з цілими числами

class TInt{

int EndState;

public

int x;

Int(int x1);

virtual ~Int();

virtual void GetEvent (TEvent &event);

virtual int Exicute();

virtual void HandleEvent (TEvent& event);

virtual void ClearEvent (TEvent& event);

int Valid();

void EndExec();

int GetX();

void SetX (int newX);

void AddY (int Y);

};

Розглянемо можливу реалізацію основних методів.

void TInit::GetEvent(TEvent &event)

{char* OpInt = “+-*/=?q”; //рядок містить коди операцій

char s[20];

char code;

cout<<‘>’;

cin>>s; code = s[1];

if(Test(char code,char*OpInt) //Функції Test перевіряє, чи входить символ

//code у рядок OpInt

{event.what = evMessage;

swith(code)

{case ‘+’: event.command=cmAdd;

break;

case‘q’: event.command = cmQuit;

break;

}

//виділити другий параметр, перевести його в тип int і привласнити полю A

};

else event.what= evNothing

};

 

int TMyApp::Execute()

{do{endState=0;

GetEvent(event); //одержати подію.

HandleEvent(event); //обробити подію.

if(event.what!=evNothing) //подія залишилася не обробленою.

while(!Valid());

return endState;

}

void TInt::HandleEvent(TEvent& event)

{

if( event.what == evMessage)

{

switch( event.message.command )

{

case cmAdd:Add(event.A);

СlearEvent( event );

break;

case cmQuit:EndExec();

СlearEvent( event );

break;

};

};

}

int TInt::Valid();

{ if (EndState == 0) return 0;

else return 1;

}

void TInt::ClearEvent(TEvent& event)

{

Event. what:= evNothing;

}

void TInt::EndExec()

{

EndState= 1;

}

void TInt::AddY(int Y)

{

x+=Y;

і т.д.

void main()

{

TInt MyApp;

MyApp.Execute();

}







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.