curs03_introducere in poo

10
1 Curs 3 Partea I-a : Introducere in POO .......................................................................................................................... 1 1. Scurt istoric ................................................................................................................................................ 1 1.1. Limbajul C ........................................................................................................................................... 1 1.2. Limbajul C++ ....................................................................................................................................... 2 2. Programare structurată versus POO .......................................................................................................... 3 2.1. Programe și modele ............................................................................................................................ 3 2.2. Programarea structurată .................................................................................................................... 4 2.3. Programarea orientată-obiect ............................................................................................................ 5 2.4. Exemplu de programare procedurală versus POO .............................................................................. 7 2.5. Definiția POO ...................................................................................................................................... 9 2.6. Rezolvarea problemelor cu POO ....................................................................................................... 10 Partea I-a : Introducere in POO 1. Scurt istoric 1.1. Limbajul C Limbajul de programare C este fundamentul lui C++, și de fapt C-ul este baza a multor limbaje moderne, cum ar fi Java, J avaScript, Pearl, PHP, Python și multe altele. Desigur C++ este descendenul direct al limbajului C și chiar include întregul limbaj C. De aceea a învăța C ar fi un prim pas ajutător pentru a învăța C++. Dezvoltat de către Dennis Ritchie și Brian Kerningham la Bell Labs in 1969, C -ul a fost destinat ca o alternativă pentru limbajul de asamblare pentru a crea sisteme de operare, utilitare și alte coduri la nivel de sistem. C-ul este un limbaj mic, cu doar 32 de cuvinte-cheie. Nu este ceea ce am numi azi un limbaj de nivel înalt, dimpotrivă, este mic, eficient, rapid și puternic. Dacă privim la nivelurile de tehnologie ale unui computer ca la o stivă, C -ul este în mod curent folosit pentru a scrie cod la toate nivelurile, dar cel mai frecvent e utilizat pentru nivelurile joase (Fig.1). Aproape tot ce este firmware, aproape toate sistemele de operare moderne și o parte însemnată a softurilor de aplicații sunt scrise în C. Fig.1 De ce oare să fie C-ul așa de răspândit? 1) Codul sistemelor scris în C tinde să fie mic și foarte rapid . Un program bine scris în C poate genera un cod-obiect care este aproape la fel de mic și de rapid ca și codul scris în limbaj de asamblare.

Upload: anon52802729

Post on 04-Jan-2016

243 views

Category:

Documents


0 download

DESCRIPTION

C++

TRANSCRIPT

Page 1: Curs03_Introducere in POO

1

Curs 3

Partea I-a : Introducere in POO .......................................................................................................................... 1

1. Scurt istoric ................................................................................................................................................ 1

1.1. Limbajul C ........................................................................................................................................... 1

1.2. Limbajul C++ ....................................................................................................................................... 2

2. Programare structurată versus POO .......................................................................................................... 3

2.1. Programe și modele ............................................................................................................................ 3

2.2. Programarea structurată .................................................................................................................... 4

2.3. Programarea orientată-obiect ............................................................................................................ 5

2.4. Exemplu de programare procedurală versus POO .............................................................................. 7

2.5. Definiția POO ...................................................................................................................................... 9

2.6. Rezolvarea problemelor cu POO ....................................................................................................... 10

Partea I-a : Introducere in POO

1. Scurt istoric

1.1. Limbajul C

Limbajul de programare C este fundamentul lui C++, și de fapt C-ul este baza a multor

limbaje moderne, cum ar fi Java, JavaScript, Pearl, PHP, Python și multe altele. Desigur C++ este

descendenul direct al limbajului C și chiar include întregul limbaj C. De aceea a învăța C ar fi un

prim pas ajutător pentru a învăța C++.

Dezvoltat de către Dennis Ritchie și Brian Kerningham la Bell Labs in 1969, C-ul a fost

destinat ca o alternativă pentru limbajul de asamblare pentru a crea sisteme de operare, utilitare și alte

coduri la nivel de sistem. C-ul este un limbaj mic, cu doar 32 de cuvinte-cheie. Nu este ceea ce am

numi azi un limbaj de nivel înalt, dimpotrivă, este mic, eficient, rapid și puternic.

Dacă privim la nivelurile de tehnologie ale unui computer ca la o stivă, C-ul este în mod

curent folosit pentru a scrie cod la toate nivelurile, dar cel mai frecvent e utilizat pentru nivelurile

joase (Fig.1). Aproape tot ce este firmware, aproape toate sistemele de operare moderne și o parte

însemnată a softurilor de aplicații sunt scrise în C.

Fig.1

De ce oare să fie C-ul așa de răspândit?

1) Codul sistemelor scris în C tinde să fie mic și foarte rapid. Un program bine scris în C poate

genera un cod-obiect care este aproape la fel de mic și de rapid ca și codul scris în limbaj de

asamblare.

Page 2: Curs03_Introducere in POO

2

2) Codul scris în C este extrem de portabil. C-ul a fost inițial destinat pentru a scrie sisteme de

operare. De exemplu sistemul de operare Unix a fost scris în C și el funcționează pe foarte

multe procesoare diferite și configurații hardware diverse. Practic acest sistem de operare se

compilează și se execută pe o mare diversitate de mașini de calcul, arhitecturi și procesoare,

fără nicio modificare sau, pe alocuri, cu foarte puține modificări ale codului-sursă. Acest

lucru este valabil și pentru aplicațiile scrise în C.

3) Limbajul în sine este relativ mic și simplu, dar foarte puternic. Simplitatea lui însă e

amăgitoare. El îți oferă un acces atât de mare la mașina de calcul încât se poate spune că e

foarte flxibil, bogat și puternic.

C-ul este un limbaj de nivel scăzut. Acest lucru înseamnă că el se apropie foarte mult de

mașina de calcul. Nu are foarte multe funcționalități dar se compilează într-un cod rapid și

eficient. De aceea și acum, după mai bine de 40 de ani, oamenii continua să folosească C.

C-ul este un limbaj imperativ. Acest lucru înseamnă că pentru a scrie codul se utilizează

instrucțiuni. Subrutinele se numesc funcții și argumentele acestora se transmit totdeauna prin

valoare.

C-ul este un limbaj procedural structurat orientat pe blocuri. Acest lucru înseamnă că tot

codul este scris în blocuri și blocurile sunt structurate pentru a mări claritatea programelor.

C-ul este un limbaj puternic tipizat. Acest lucru înseamnă că fiecare variabilă trebuie să aibă

un anumit tip declarat. Declarațiile de tip sunt analizate în timpul compilării și nu se pot

modifica pe parcursul duratei de viață a variabilelor respective. Avantajul unui limbaj puternic

tipizat este faptul că performanța este mult îmbunătățită în comparație cu limbaje similare de

programare tipizate dinamic. Într-un sistem tipizat dinamic puterea de procesare în timpul

execuției este utilizată pentru a determina tipul unei variabile și pentru a creea copii de lucru

cu structurile de date adecvate pentru fiecare variabilă și apoi se repetă aceste acțiuni când

variabila se modifică. Prin determinarea tipului variabilei la compilare toate aceste acțiuni

enunțate mai sus sunt eliminate.

1.2. Limbajul C++

C++, numit la început "C with classes" a fost dezvoltat în 1979-1980 de către danezul Bjarne

Stroustrup. Acesta a dus la îmbunatatirea C-ului prin adăugarea unor noi facilități, printre care cea

mai importantă a fost lucrul cu clase și obiecte, deci paradigma de programare orientată pe obiecte

(POO).

Totuși, mult înainte deja, în anii '60, în sprjinul aplicațiilor destinate inteligenței artificiale, au

apărut limbaje care presupun faptul că e nevoie de obiecte care să nu fie simple elemente pasive

asupra cărora se fac anumite prelucrări, ci, dimpotrivă, că menirea acestor obiecte constă în a realiza

prelucrările asupra lor înșile. De aici a pornit ideea de a grupa structurile de date cu operațiile care

prelucrează respectivele date. Astfel s-a născut noțiunea de obiect sau clasă. Proiectarea de programe

utilizând clase se numește programare orientată pe obiecte (POO). Primele limbaje orientate pe

obiecte au fost SIMULA (1965) si SIMULA-2 (1967). In anii '70 a apărut și celebrul limbaj

SMALLTALK. Cel mai mare dezavantaj al lor a fost faptul că au apărut ca limbaje de sine stătătoare,

având o răspândire relativ redusă. Din acest motiv, puțini programatori erau dispuși în acea vreme să

renunțe la limbajele consacrate doar pentru a lucra obiectual.

În vara 1983, C-with-classes a pătruns și în lumea academică și a instituțiilor de cercetare.

Astfel, acest limbaj a putut să evolueze datorită experienței acumulate de către utilizatorii săi.

Page 3: Curs03_Introducere in POO

3

Succesul extraordinar pe care îl are limbajul C++ a fost asigurat de faptul că s-a folosit de cel mai

popular limbaj al momentului, C.

C++ este un limbaj de uz general foarte puternic și flexibil, care permite programarea în mai

multe paradigme, cum ar fi paradigma orientată-obiect, cea procedurală, funcțională și programare

generică. Așa cum s-a mai spus, C++ extinde limbajul C, adăugând multe facilitate puternice, dar

menținând în același timp eficiența și utilitatea C-ului. Aceasta îl face să fie și astăzi, după mai bine

de 30 de ani, unul din cele mai răspândite limbaje de programare din lume.

Dacă privim la nivelurile de tehnologie ale unui computer ca la o stivă, C++ este folosit

pentru a scrie cod la toate nivelurile cu excepția firmware-ului, având cea mai largă utilizare la

nivelul aplicațiilor (Fig.2).

Fig. 2

Astăzi un număr mare de aplicații pe scară medie și largă sunt scrise în C++. Lista unor astfel

de aplicații este foarte vastă, și include Microsoft Office, Adobe Photoshop, Illustrater, FireFox,

Google Chrome, sisteme de aprovizionare, service și evidență a plăților pentru telefonie și internet,

chiar și site-uri web renumite, ca Amazon, Facebook și Google sunt scrise integral în C++ sau au

resurse back-end semnificative scrise în C++. Sisteme de operare cum ar fi toate versiunile de

Windows începând cu 1.0, părți din Unix care nu sunt scrise în C, părți mari din OS10 (alte părți

fiind în Objective C, care e la rândul său bazat pe C). De fapt majoritatea celorlalte limbaje de

programare, cum ar fi Java, PHP, Python și Pearl sunt scrise în C sau C++.

2. Programare structurată versus POO

2.1. Programe și modele

Aproape toate programele modelează o problemă din lumea reală.

Un model este o reprezentare simplificată sau o abstracțiune a unui sistem.

Modelul evidențiază doar caracteristicile importante într-un anumit context ale sistemului

reprezentat. De exemplu, o mașină de jucărie prezintă anumite detalii exterioare cum ar fi carcasa și

roțile, dar nu include componente ca: motorul, rezervorul etc.

Într-un program, elementele cu ajutorul cărora realizăm modelarea sunt:

structurile de date și

secvențele de instrucțiuni sau operațiile.

În funcție de limbajul de programare utilizat, construcțiile care redau structurile de date și

operațiile sunt mai mult sau mai puțin expresive, adică mai mult sau mai puțin apropiate de obiectele

ce formează domeniul problemei de rezolvat.

La nivelul cel mai de jos, din acest punct de vedere, se situează limbajele-mașină și apoi

limbajele de asamblare, care dispun de structuri de date și operații primitive cu care nu se pot modela

probleme complexe.

Page 4: Curs03_Introducere in POO

4

2.2. Programarea structurată

Limbajele de nivel înalt așa-numite structurate (de genul Basic, Pascal si C) aduc o creștere

substanțială a nivelului de abstractizare mai ales în exprimarea operațiilor. Acestea sunt redate cu

ajutorul structurilor de control (structuri liniare, alternative și repetitive), iar "cărămizile" din care

este construit un program sunt subprogramele (funcțiile și procedurile). Structurile de date oferite de

aceste limbaje rămân însă destul de sărace pentru a acoperi complexitatea problemelor de rezolvat.

Limbajele structurate au inspirat metodele procedurale folosite la dezvoltarea produselor

software; ele se caracterizează prin:

Un program conceput conform unei metode procedurale pune accentul pe algoritmii care

transformă datele inițiale ale unei probleme în rezultate.

Algoritmii sunt structurați în subprograme cărora li se furnizează date sub formă de

parametri sau care accesează datele respective prin intermediul unui fond global comun

(fig.3).

Fig. 3

Programarea structurată (oferită de C spre exemplu) oferea două mari avantaje:

1.) Modularizarea – ceea ce înseamnă descompunerea unei probleme complexe în

subprobleme până se obțin probleme foarte simple și relativ independente. Pentru fiecare

problemă simplă se scrie apoi un modul de program corespunzător, și el simplu. Fiecare

modul de program execută un grup de prelucrări independente de grupurile de prelucrări

ale celorlaltor module. La nevoie modulele comunică între ele prin interfețe constituite

din seturi de parametri. Relativa independență a modulelor permite efectuarea operațiilor

specifice de implementare, testare, depanare și modificare în mod independent de

celelalte module.

2.) Structurarea datelor și a prelucrării lor: Datele se grupează în colecții organizate după

reguli potrivite, astfel rezultând structuri de date. Prelucrările datelor se pot organiza

conform a cel puțin trei structuri fundamentale: structura liniară (secvențială), structura

alternativă și structura repetitivă.

Totuși, programarea structurată a fost o etapă ce a trebuit să fie depășită, deoarece este

deficitară în ceea ce privește posibilitatea reutilizării programelor, a scalabilității și extinderii unor

module de program, atribute de neînlocuit în realizarea aplicațiilor complexe. Principala deficiență

a programării structurate constă în tratarea separată a algoritmilor și a structurilor de date ce se

Page 5: Curs03_Introducere in POO

5

prelucrează. De obicei, în natură, o entitate este caracterizata atât printr-o structură, cât și printr-un

anume comportament. În mod normal, obiectele evoluează în timp, adeseori modificându-și structura

și funcționalitatea.

2.3. Programarea orientată-obiect

Limbajele de programare orientate pe obiecte (LPOO) aduc o nouă viziune asupra

dezvoltării programelor, urmărind să acopere "slăbiciunile" limbajelor structurate privind structurile

de date. Mai precis, programatorului i se dă posibilitatea de a-și construi propriile tipuri de date,

dotate cu operațiile necesare, care să "mimeze" cât mai fidel entitățile din domeniul problemei de

rezolvat.

Cu toate că avantajele programării orientate pe obiecte (POO) vor deveni tot mai clare pe

măsură ce parcurgeți acest curs de POO, ar fi poate util în acest punct să marcăm o paralelă între

POO și lumea înconjurătoare.

Obiectele sunt cheia înțelegerii tehnologiei OO. Privind în jur veți vedea o sumedenie de

obiecte care vă înconjoară în lumea reală: pisica, patul, telefonul, bicicleta etc.

Obiectele din lumea reală au două caracteristici: Toate au niște atribute de stare și unele

comportamente/operații. Spre exemplu pisicile au atribute de stare (nume, culoare, rasă) și

comportamente (mieunat, zgâriat, mâncat). Bicicletele de asemenea au atribute de stare (viteza

curentă, cadența de pedalare) și operații (schimbarea de viteză, schimbarea cadenței, frânare).

Identificarea atributelor și operațiilor/comportamentelor pentru obiectele din lumea reală este un bun

început pentru a ne obișnui cu gândirea în termenii POO.

Luați-vă un minut chiar acum pentru a studia obiectele din lumea reală din imediata voastră

apropiere. Pentru fiecare obiect pe care îl vedeți puneți-vă două întrebări: "În ce stări posibile poate fi

acest obiect?" și "Ce comportamente/operații posibile poate avea acest obiect?". Astfel veți observa

că obiectele din lumea reală variază în ceea ce privește complexitatea lor; lampa de birou ar putea

avea doar două posibile stări (oprită și pornită) și două posibile operații (pornire, oprire), însă un

radio ar putea avea mai multe atribute de stare (pornit, oprit, volumul curent, postul curent) și operații

(pornire, oprire, mărire volum, micșorare volum, căutare post etc). Veți putea observa de asemenea

că unele obiecte vor conține, la rândul lor, alte obiecte. Toate aceste observații din lumea reală se

regăsesc transpuse în lumea POO.

Un program dezvoltat cu ajutorul tehnologiei obiectuale are drept unitate de constructie nu

subprogramul, ci obiectul (fig.4).

Fig. 4.

Page 6: Curs03_Introducere in POO

6

Un obiect înglobează date și operații și reprezintă o abstracțiune a unei entități din

lumea reală.

Obiectele componente interacționează, iar rezultatul acestei interacțiuni o reprezintă

transformarea datelor de intrare în date de ieșire, adică rezolvarea problemei.

Folosind tehnologia obiectuală, abstractizarea (înțelegând prin aceasta tranziția de la entitățile

domeniului problemei de rezolvat la programul care o modeleaza) este mai directă, mai naturală.

Motivul stă în faptul că noi, oamenii, percepem lumea înconjurătoare în termeni de obiecte fizice și

concepte mentale care se mișcă, se transformă, interacționează unele cu altele, determinând în felul

acesta modificări ale mediului înconjurător.

Un obiect din lumea reală are câteva caracteristici importante, și anume:

este perceput prin intermediul comportamentului si insușirilor sale exterioare; de exemplu,

vedem că o pisică merge, fără să știm (și fără să ne intereseze chiar) care sunt mecanismele

interioare care determină mersul. Cu alte cuvinte, obiectul are o față exterioară (interfață

publică) pe care o arată altor obiecte, precum și o reprezentare (stare) internă care imprimă

comportarea exterioară;

are granițe distinct conturate, care îl delimitează de celelalte obiecte și este autodeterminat:

pastrând exemplul cu pisica, pentru a vedea că ea merge, nu avem nevoie să vedem un alt

obiect suplimentar; spunem că obiectul are identitate distinctă;

În cazul programării procedurale abstractizarea presupune realizarea unui set de algoritmi

(subprograme) care să modeleze transformările din lumea reală, folosind pentru reprezentarea unor

entități complexe structuri de date primitive.

În cazul programării obiectuale, abstractizarea presupune definirea unor structuri de date

complexe dotate cu un comportament exterior și cu o stare internă, care se suprapun peste obiectele

din lumea reală.

Într-un program dezvoltat în manieră obiectuală NU mai avem date globale (sau în orice caz,

foarte puține). Datele sunt repartizate și înglobate în obiecte. Putem spune că metoda obiectuală de

dezvoltare conduce la o mai bună respectare a unor principii ale ingineriei software cum ar fi:

localizarea și modularizarea: codul sursă corespunzător unui obiect poate fi scris și

actualizat independent de alte obiecte;

ascunderea informației: un obiect are, după cum vom vedea în curând, o interfață publică pe

care celelalte obiecte o pot utiliza în vederea comunicării. Dar, pe lângă interfața publică, un

obiect poate include date și operații private, "ascunse" față de alte obiecte, și care pot fi

modificate oricând, fără a afecta restul obiectelor.

reutilizarea codului: multe clase de obiecte pot fi definite pe baza altor clase deja existente,

preluându-se automat (prin moștenire) conținutul acestora din urmă;

Trecand la un limbaj de programare orientat pe obiecte nu înseamna că "aruncăm" principiile

programării structurate. Operațiile înglobate în obiecte nu sunt altceva decât un fel de subprograme

(chiar dacă au alt nume) care vor fi dezvoltate utilizând structurile de control cunoscute de la

limbajele structurate.

Într-o exprimare plastică:

Diferența esențială între limbajele procedurale și cele obiectuale este aceea că limbajele

procedurale au un caracter imperativ, fiind axate pe "verbe" (subprograme), în timp ce

Page 7: Curs03_Introducere in POO

7

limbajele obiectuale au un caracter mai declarativ și sunt concentrate în jurul

"substantivelor" (datele).

Ținând cont de cele afirmate pâna aici, putem formula principiul după care realizăm

transpunerea enunțului unei probleme într-un LPOO:

identificăm obiectele ce populează spațiul programului, prin evidențierea substantivelor din

enunțul problemei;

pentru fiecare obiect identificăm datele și operațiile, prin evidențierea adjectivelor și

verbelor ce caracterizează substantivul respectiv.

În ultimii ani, POO a devenit foarte răspândită, mai ales datorită avantajelor sale, care ajută

dezvoltării proiectelor actuale, ce devin din ce în ce mai complexe. Acest stil de programare duce la

împărțirea aplicațiilor în mai multe module, astfel încât cel ce dezvoltă un modul nu trebuie să

cunoască detaliile de implementare a altor module. Domeniul în care acest stil de programare s-a

dovedit cel mai util este dezvoltarea interfețelor utilizator și a aplicațiilor bazate pe acestea.

Limbaje OO utilizate astăzi pe scară largă sunt foarte multe la număr, începând cu C++,

Objective-C, C#, Visual Basic.NET, VBScript, F#, Visual FoxPro, Visual Prolog, Java, Perl începând

cu versiunea 5, PHP5, Python, ABAP ș.a.

2.4. Exemplu de programare procedurală versus POO

În cele ce urmează vom prezenta un exemplu de problemă modelată în manieră procedurală și

în manieră obiectuală, pentru a vedea mai bine diferențele între cele două viziuni.

Problema se referă la crearea și utilizarea unei stive de numere întregi. După cum probabil

stiți, o stivă este o colecție cu structură liniară, în/din care se pot introduce/extrage elemente pe la un

singur capăt, considerat a fi vârful stivei (celălalt capăt este baza). Operațiile asupra stivei au

denumiri consacrate în literatură, și anume: introducerea elementelor este numită push, iar extragerea

- pop; în plus, există o operație de consultare a valorii din vârful stivei, numită top.

Pentru a nu vă solicita atenția cu detalii sintactico-semantice specifice unui anumit limbaj de

programare, vom considera că dispunem de un fel de pseudo-cod pentru ambele maniere de

modelare. Convenim ca pentru reprezentarea stivei să folosim un tablou cu elemente întregi, căruia i

se asociază un indicator de stivă reprezentând indicele ultimului element ocupat în tablou. De

asemenea, vom folosi o variabilă necesară memorării dimensiunii totale a tabloului.

-- Stiva in varianta procedurala --

subprogram initStiva(unTab, dimTab,

indTab){

*aloca spatiu in unTab pentru dimTab

elemente

indTab = -1;

-- se considera ca indicele primului

element din tablou este 0 --

}

subprogram push(unTab, dimTab, spTab,

elem){

if (indTab < dimTab-1){

spTab = spTab + 1;

-- Stiva in varianta obiectuala --

clasa Stiva{

*fie tab un tablou cu elemente de tip

int

*fie dimTab o variabila de tip int

*fie indTab o variabila de tip int

operatia initStiva(nrElem){

*aloca spatiu in tab pentru nrElem

elemente

dimTab = nrElem;

indTab = -1;

-- se considera ca indicele

primului element din tablou este 0

Page 8: Curs03_Introducere in POO

8

unTab[indTab] = elem;

}

else

*semnaleaza eroare - depasire

capacitate stiva

}

subprogram int pop(unTab, dimTab, indTab){

if (indTab >= 0){

indTab = indTab - 1;

return unTab[indTab+1];

}

else

*semnaleaza eroare - stiva

vida

}

subprogram int top(unTab, dimTab, indTab){

if (indTab >= 0)

return unTab[indTab];

else

*semnaleaza eroare - stiva

vida

}

subprogram client( ){

*fie tab1, tab2, tab3 numele unor

tablouri cu elemente de tip int

*fie dim1, dim2, dim3 variabile care

memoreaza dimensiunile tablourilor

*fie ind1, ind2, ind3 variabile cu

rol de indicatori de stiva

dim1 = 10;

dim2 = 5;

dim3 = 6;

-- se initializeaza stivele --

call initStiva(tab1, dim1, ind1);

call initStiva(tab2, dim2, ind2);

call initStiva(tab3, dim3, ind3);

-- se introduc elemente in stive --

call push(tab1, dim1, ind1, 17);

call push(tab1, dim1, ind1, 100);

call push(tab2, dim2, ind2, 26);

call push(tab2, dim2, ind2, 15);

-- se extrag elemente din stive --

e1 = call pop(tab1, dim1, ind1);

e2 = call pop(tab2, dim2, ind2);

-- se consulta valorile din varful

stivelor --

x1 = call top(tab1, dim1, sp1);

x2 = call top(tab2, dim2, sp2);

...

}

--

}

operatia push(elem){

if (indTab < dimTab-1){

indTab = indTab + 1;

tab[indTab] = elem;

}

else

*semnaleaza eroare -

depasire capacitate stiva

}

operatia int pop( ){

if (indTab >= 0){

indTab = indTab - 1;

return tab[indTab+1];

}

else

*semnaleaza eroare - stiva

vida

}

operatia int top( ){

if (indTab >= 0)

return tab[indTab];

else

*semnaleaza eroare - stiva

vida

}

}

} -- end clasa Stiva --

clasa Client( ){

operatia prelucrareStiva( ){

*creaza obiectele s1, s2 si s3 de

tip Stiva

-- se initializeaza stivele --

call s1.initStiva(10);

call s2.initStiva(5);

call s3.initStiva(6);

-- se introduc elemente in stive -

-

call s1.push(17);

call s1.push(100);

call s2.push(26);

call s2.push(15);

-- se extrag elemente din stive --

e1 = call s1.pop( );

e2 = call s2.pop( );

-- se consulta valorile din varful

stivelor --

x1 = call s1.top( );

x2 = call s2.top( );

...

Page 9: Curs03_Introducere in POO

9

}

} -- end clasa Client --

Comparând cele două secvențe de mai sus, un prim aspect care trebuie remarcat este faptul că

în varianta procedurală am definit un set de operații reprezentate ca subprograme, care primesc ca

parametri stivele asupra cărora lucrează, în timp ce în varianta obiectuală, operațiile sunt înglobate în

interiorul unui obiect reprezentând stiva. Pot să am oricâte obiecte de acest fel, fiecare din ele va avea

setul său propriu de operații care vor lucra asupra datelor interne ale obiectului. Din acest motiv

operațiile nu necesită atâția parametri, ca în varianta procedurală. Cu alte cuvinte: În varianta

procedurală operațiile (subprogramele) sunt deținătoarele datelor asupra cărora lucrează, în timp

ce în varianta obiectuală datele (obiectele) sunt cele care posedă operațiile.

O alta observație importantă este faptul că simbolul Stiva definit ca o clasă este de fapt un tip

definit de utilizator. Ca orice tip, el poate fi folosit pentru a declara variabile asupra cărora se vor

aplica operații recunoscute de tipul respectiv.

Pentru a înțelege mai bine, să ne gândim ce este un tip dintr-un limbaj de programare:

Un tip este o mulțime de valori dotată cu un anumit set de operații.

În majoritatea limbajelor procedurale suntem obișnuiți să lucrăm cu așa-numitele

tipuri predefinite sau primitive. Spre exemplu, tipul int din limbajul C desemnează mulțimea

numerelor întregi reprezentabile pe 2 octeți. Setul de operații cu care este dotat acest tip cuprinde,

printre altele, cele patru operații aritmetice.

De multe ori tipurile predefinite sunt prea sărace pentru a permite modelarea unor entități

complexe din lumea reală. De aceea, este necesar ca programatorul să aibă libertatea de a-și crea

propriile tipuri (împreuna cu operațiile aferente) pe care apoi să le foloseasca la fel cum folosește

tipurile predefinite. Limbajele de programare obiectuale au fost concepute tocmai în acest sens.

Tot pe marginea celor două exemple prezentate, ar trebui spus că în varianta obiectuală

programatorul este ajutat să evite o serie întreagă de erori, datorită încapsulării datelor și operațiilor

caracteristice unei abstracțiuni (în cazul nostru stiva) în interiorul unui obiect. Spre exemplu, în

varianta procedurală, programatorul poate la un moment dat să modifice accidental, printr-o atribuire

simplă, valoarea lui ind1, dând astfel peste cap stiva respectivă. În cealaltă variantă, așa cum vom

vedea pe parcurs, datele din interiorul unui obiect pot fi declarate ca ascunse față de exteriorul

obiectului, astfel încât modificarea indicatorului de stivă să nu se poată face decât via

operațiile push și pop, adică într-un mod controlat.

2.5. Definiția POO

Programarea orientată pe obiecte este o metoda de implementare în care programele

sunt organizate ca ansamble de obiecte ce interacționează unele cu altele, fiecare obiect

reprezentând instanța unei clase; fiecare clasă aparține unei ierarhii în cadrul căreia

clasele sunt legate prin relații de moștenire.

Aceasta definiție cuprinde trei părți importante, și anume:

obiectele și nu algoritmii sunt blocurile logice fundamentale;

Page 10: Curs03_Introducere in POO

10

fiecare obiect este o instanță a unei clase. Clasa este o descriere a unei mulțimi de obiecte

caracterizate prin structură și comportament similare, iar prin instanță înțelegem o

valoare particulară din mulțimea respectivă

clasele sunt legate între ele prin relații de moștenire.

Un limbaj de programare care oferă suport pentru utilizarea claselor și a obiectelor, dar care

nu are implementat mecanismul relațiilor de moștenire între clase este un limbaj de programare bazat

pe obiecte. Programarea bazată pe clase și pe obiecte, care nu face uz de relația de moștenire se mai

numește programare cu tipuri de date abstracte.

2.6. Rezolvarea problemelor cu POO

Pentru a rezolva cu ajutorul POO probleme ce implică sisteme nu foarte complexe, trebuie să

știți cel puțin două lucruri:

1°) În primul rând, desigur, trebuie să învățați sintaxa specifică limbajelor de programare.

Aceasta nu înseamnă să învățați pe de rost sintaxe, atâta timp cât dispuneți de resurse și

documentații web în cantitate mai mult decât suficientă. Dar, fără o cunoaștere bună a

structurilor și mecanismelor puse la dispoziție de limbajul de programare, nu veți putea

realiza o soluție pentru problema propusă.

2°) Pe lângă sintaxa limbajului va trebui să vă însușiți pentru fiecare limbaj conceptele de

încapsulare, moștenire și polimorfism, deoarece aceste trei concepte reprezintă baza

oricărui limbaj orientat-obiect. Modul cum funcționează fiecare concept variază într-o

măsură mai mica sau mai mare de la limbaj la limbaj. De exemplu, C++ permite

moștenire multiplă, ceea ce dă programatorului anumite libertăți, dar crește riscul de a

scrie cod eronat. Pe de altă parte Java interzice moștenirea multiplă în sensul permis de

către C++, permite însă unei clase să moștenească de la oricâte interfețe. Tot la fel,

specificatorii de acces, care permit încapsularea informației într-o clasă cu diferite

niveluri de acces, funcționează ușor diferit în C++ față de Java. În plus, Java are

conceptul de package care are legătură cu controlul accesului - un concept care nu există

în C++. Polimorfismul permite unui tip dintr-o subclasă să fie tratat ca un tip de

superclasă. Cu toate că funcționează în esență la fel în toate limbajele OO, modul în care

polimorfismul este invocat poate duce la constrângeri importante asupra programării. În

C++ de exemplu, polimorfismul poate fi invocat numai prin pointeri, un fapt care poate

avea o mare semnificație asupra modului cum se poate referi un obiect într-un program.

Pentru sisteme complexe intervine și un al treilea lucru important, și anume:

3°) Cunoașterea unui "meta-limbaj", cum ar fi Unified Modeling Language (UML), care

permite reprezentarea vizuală a proiectării la nivel conceptual, și respectiv învățarea

șabloanelor de design (design patterns), acestea fiind soluții template pentru o mulțime de

subprobleme posibil de înfruntat pe parcursul dezvoltării unui program OO.

Pentru acest curs vom dezvolta primele două puncte de mai sus (punctul 3°, UML, depășește

cadrul acestui curs) utilizând limbajul C++. Am ales acest limbaj deoarece C++ este, într-un fel, baza

pe care au fost construite multe din celelalte limbaje OO, după cum s-a arătat la începutul acestui

capitol. Pentru început, vom trece sumar în revistă fundamentele limbajului C++, structurile de

control și tipurile de date compuse, pentru ca apoi să dezvoltăm capitolele legate strict de conceptele

de POO.