Sunteți pe pagina 1din 65

Universitatea TRANSILVANIA din Braov

Facultatea de Matematic i Informatic


Catedra de Informatic Aplicat

Iniiere n
programarea orientat pe
obiecte din perspectiv Java

Dorin Bocu

REPROGRAFIA UNIVERSITII TRANSILVANIA DIN BRAOV

...O parte din eforturile tiinei calculatoarelor sunt dedicate mbuntirii


permanente a paradigmelor de modelare. Prin istoric i prin realizrile de ultim
or, ingineria softului nu face dect s confirme aceast aseriune. Modelarea
orientat pe obiecte este un exemplu remarcabil de instrument, gndit pentru a
fi utilizat n realizarea de sisteme soft, competitive din punct de vedere al
preului i al calitii. Programarea orientat pe obiecte ngduie fanilor ei s
verifice, n practic, fora unui stil de a modela, a crui capacitate de a mapa
domeniul problemei peste domeniul soluiei este cu mult superioar altor
paradigme.

Cuvnt nainte al autorului


Au trecut ani buni de cnd lumea a nceput s ntrebuineze, n vorbire i n alte contexte, sintagma
programare obiect orientat sau, ceva mai aproape de spiritul limbii romne, programare orientat pe
obiecte. Pregtit i anunat de numeroasele controverse pe marginea preamultelor slbiciuni ale vechilor
paradigme de programare, orientarea pe obiecte s-a instalat confortabil de-a lungul ntregului proces de
dezvoltare a unui sistem soft, devenind n zilele noastre religia care guverneaz att etapa de modelare a
unui sistem soft ct i etapa de implementare. Au aprut limbaje, precum i medii de programare i
dezvoltare a sistemelor soft, a cror arhitectur este esenial tributar ideii de orientare pe obiecte (Java, C++,
C#, Object Pascal cteva exemple mai cunoscute de limbaje, Delphi, C-Builder, Visual C++ - cteva exemple
mai cunoscute de medii de programare, Rational Rose, ObjectiF dou dintre mediile de dezvoltare cu bun
rspndire n lumea ingineriei softului).
Este clar, orientarea pe obiecte nu este doar o mod n programare, ci o modalitate, fr rival,
pentru moment, de a dezvolta sisteme soft.
Pentru informaticienii a cror practic se reduce la apropierea ct mai rapid de tastatur pentru a
rezolva o problem, orientarea pe obiecte este o ncercare care tulbur minile i ntrzie rezolvarea
problemei. Seriile de studeni care mi-au trecut prin mn mi-au ntrit convingerea c nsuirea spiritului
orientrii pe obiecte este o problem destul de dificil, deoarece, aproape tot ceea ce este reclamat de
obnuinele omului n materie de nvare, este dificil de operaionalizat cnd este vorba de nsuirea acestui
spirit. Mult mai apsat dect n alte paradigme, n orientarea pe obiecte, specialistul trebuie s acorde atenia
cuvenit elaborrii soluiei nainte de a o implementa. Metodele cele mai rspndite de nvare a limbajelor
de programare se bazeaz pe formula:
Prin aplicaii, spre descoperirea subtilitilor sintactice, semantice i pragmatice ale unui limbaj
de programare.
Cititorul atent a neles faptul c nvarea unui limbaj de programare este un exerciiu de voin care
presupune parcurgerea a trei etaje:

nvarea stereotipurilor sintactice fundamentale ale limbajului (sintaxa limbajului)


Descoperirea unui numr ct mai mare de semantici primitive, care pot fi nvelite cu sintaxa limbajului
(semantica limbajului)
Formarea unor deprinderi de utilizare eficient a limbajului, n funcie de natura i complexitatea
problemei, pentru rezolvarea respectivei probleme (pragmatica limbajului).

Ideea cluzitoare a acestui support de curs este de a invita cititorul s nvee singur sintaxa
orientrii pe obiecte, ncercnd s l ajute, ndeosebi n efortul de deconspirare a semanticii i pragmaticii
orientrii pe obiecte.
Trimiterile de natur sintactic vor fi raportate la limbajul Java.
Trebuie s mrturisesc, totodat, faptul c, n viziunea acestei lucrri, fiecare cititor este o instan
cognitiv activ, capabil de efort permanent de abstractizare, singura modalitate de a ajunge la o
nelegere superioar a esenei unei paradigme de modelare i, n particular, de programare.
Atitudinea de spectator, cu instinct de conservare puternic, la derularea ideilor din aceast lucrare, este
absolut contraproductiv pentru atingerea obiectivului fundamental: nvarea ct mai multor elemente suport, eseniale pentru modelarea / programarea orientat pe obiecte a soluiei unei probleme.
Ce se va ntmpla cu cei care nu se vor putea mpca cu ideea de a se dezmori voluntar, iat o
problem n legtur cu care prefer s spun doar att: nu peste mult timp vor descoperi c au mbtrnit
nainte de vreme, fr a fi neles mare lucru despre plcerea de a uita de scurgerea timpului, realiznd
lucruri care s uimeasc, deopotriv, pe alii i pe propriul lor creator.
Referindu-m la studenii pentru care, n principal, am scris aceast lucrare, trebuie s spun c, n
viziunea mea, ideea de student se confund cu imaginea unui individ care are apeten pentru studiu.
Dac, n facultate, se mai studiaz i discipline care, unora li se par, nefolositioare, datoria studentului este s
fac efortul de a se identifica cu ideile fundamentale ale unui numr ct mai mare de discipline, socotite de el
folositoare. Dac, n facultate, studenii se mai ntlnesac i cu profesori ale cror cutri nu sunt nc suficient
de bine sistematizate, acesta nu este un motiv de a renuna la dorina de a cunoate.
De la natur, studentul poate fi asimilat cu un obiect care are toate capabilitile necesare pentru a
parcurge drumul dificil, dar pasionant, al cunoaterii elementelor fundamentale, n diferite ramuri ale
matematicii i tiinei calculatoarelor.

A aminti, tuturor celor care nu au realizat nc, faptul c omul are nevoie de tiin pentru a nelege o
parte din realitatea necunoscut (rezult c tiina are funcie explicativ), pentru a modela comportamentul
unor fenomene i procese din realitatea obiectiv, n vederea optimizrii dinamicii lor (rezult c tiina are
funcie modelatoare), pentru a mbogi realitatea obiectiv cu obiecte artificiale (rezult c tiina are funcie
demiurgic).
Sper ca cititorul s neleag bine rolul activ pe care trebuie s i-l asume n deconspirarea, prin studiu
individual i exerciii perseverente, a etajelor sintactice eseniale programrii n Java.

1 Cum se explic permanenta nevoie de paradigme


noi n ingineria softului. Ce nelegem prin
orientarea pe obiecte
1.1 Cum se explic permanenta nevoie de paradigme noi n ingineria
softului?
Binefacere sau blestem, omenirea este, asemenea ntregului univers, ntr-o continu deplasare spre alte
repere ontologice i gnoseologice. Avea dreptate Heraclit din Efes cnd, folosind cuvinte meteugit alese,
constata c singura certitudine a universului pare a fi devenirea. Dac, acum peste 2500 de ani n urm,
devenirea ocupa o poziie central n modul de gndire al lui Heraclit, n zilele noastre devenirea s-a transformat
n izvor nesecat i cauz a tuturor transformrilor importante pe care le suport universul cunoscut omului. S-ar
prea c nimic din ceea ce face omul nu dureaz. Acest fapt este, dup ascuimea simurilor noastre, n opoziie
cu ceea ce Natura sau Marele Creator fac. Omul aspir la eternitate luptnd cu efemerul inerent al
creaiilor lui. Marele Creator este eternitatea nsi. Las pe seama filozofilor continuarea efortului de preamrire
sau punere la index a rolului pe care l joac devenirea n viaa omului i, de ce nu, n univers.
Caracterul obiectiv al devenirii poate explica, n genere i nevoia de paradigme 1 noi n ingineria softului
i, n particular n programare.
*
Permindu-mi o scurt digresiune, ingineria softului este o ramur a tiinei calculatoarelor care se
ocup, la urma urmei, de studierea unei probleme extrem de delicate: Dat o problem oarecare, ce trebuie
fcut pentru a o rezolva cu ajutorul calculatorului?
Confruntai de-a lungul timpului, cu diferite tipuri de probleme, specialitii n ingineria softului au fcut
o descoperire banal:
Efortul depus pentru a rezolva o problem cu ajutorul calculatorului este direct proporional cu
complexitatea problemei.
Odat fcut aceast descoperire iese la iveal alt ntrebare: Cum definim complexitatea unei
probleme? Atenie, cititorule, este vorba de complexitatea unei probleme nu de complexitatea soluiei
algoritmice a unei probleme.
Complexitatea unei probleme este o caracteristic intrinsec a enunului asumat al acesteia.
Complexitatea soluiei algoritmice a unei probleme este o caracteristic intrinsec a modului n care o
anumit instan cognitiv (de pild un student din anul II) obine respectiva soluiie algoritmic.
Este, sper, ct se poate de clar faptul c cele dou tipuri de complexitate cuantific caracteristicile
structurale ale unor colecii de obiecte, diferite din punct de vedere al sferei de cuprindere i al coninutului.
Cei care au parcurs unul sau mai multe cursuri de iniiere n Algoritmic i Programare i amintesc,
probabil, nelesul pe care l are complexitatea unui algoritm. Formalizarea matematic a complexitii
algoritmilor este un prilej minunat de a ilustra fora de analiz a matematicii de puterea continuului, aplicat
universului algoritmilor, al cror comportament este eminamente discret.
Este corect s evideniem, n acest punct, utilitatea teoretic i practic (ndeosebi n cazul aplicaiilor
critice relativ la complexitatea algoritmilor folosii) a eforturilor de clasificare a algoritmilor secveniali i
paraleli, n funcie de complexitatea lor Acest gen de afirmaii sunt prezentate n toat cuprinderea i adncimea
lor n cri fundamentale pentru nvrea programrii calculatoarelor 2.
Ingineria softului (IS) ia act de aceast realitate i, n replic, i concentreaz atenia asupra
complexitii problemelor. O ncercare de a evidenia elementele cu ajutorul crora putem descrie
complexitatea unei probleme n ingineria softului ne conduce la seria de observaii de mai jos.

Rezolvarea unei probleme cu ajutorul calculatorului nseamn, de cele mai multe ori, simularea /
asistarea de ctre calculator a unor activiti, desfurate de ctre sisteme de alt natur. Aadar,
aproape invariabil, ne aflm n faa unor dificulti care rezult din caracterul instabil al relaiei
dintre model i sistemul modelat. Neglijarea acestui aspect simplific efortul de realizare, n cele din

Este cazul s spunem c, prin paradigm se nelege, fr a exagera cu explicaiile, un mod de abordare a problemelor dintr-un anumit
domeniu, evident, cu scopul de a rezolva aceste probleme. Poate c limba romn nu avea neaprat nevoie de acest cuvnt, dar insistena cu
care este utilizat n alte pri poate fi considerat o scuz pentru utilizare a lui n aceast carte.
2
Knuth, Cormen

urm, a unui sistem soft, dar preul pltit este exprimat, sintetic, astfel: uzur moral rapid i
posibiliti de adaptare reduse. Se poate lupta cu mijloace raionale mpotriva caracterului instabil al
relaiei dintre model i sistemul modelat? Rspunsul este: da, se poate lupta, dac specialistul n IS este
dispus s anticipeze impactul posibilelor schimbri ale sistemului modelat asupra soluiei
(modelului). Anticipnd schimbrile sistemului modelat, simplificm efortul de adaptare a soluiei la
aceste schimbri.

Modelul care st la baza soluiei unei probleme abstractizeaz viziunea specialistului sau grupului de
specialiti n IS, asupra sistemului modelat. Semn al posibilitilor noastre limitate de a cunoate, orice
viziune nu poate dect s aproximeze comportamentul sistemului modelat. Chiar i n aceste condiii,
de la a aproxima defectuos pn la a aproxima inspirat este nu doar un drum lung ci i plin de
diverse tipuri de ncercri. Exemple de astfel de ncercri:
specificarea complet a cerinelor funcionale;
acordarea ateniei cuvenite cerinelor non-funcionale;
alegerea inspirat a modalitilor de armonizare a cerinelor contradictorii;
alegerea inspirat a paradigmei de modelare, etc.

Trecerea, cu succes, peste dificultile schiate mai sus este realizat n condiii ergonomice dac
managementul acestor dificulti (plus nenumrate altele) este tratat cu maximum de seriozitate i
competen.
ncercnd s form o concluzie, complexitatea unei probleme n IS este influenat de:

1.

Stabilitatea relaiei model-sistem modelat; lipsa de stabilitate n aceast relaie, asumat contient,
induce creterea complexitii problemei de rezolvat.

2.

Complexitatea structurii sistemului modelat (creterea acesteia induce,


complexitii problemei de rezolvat).

3.

Desfurarea n condiii de eficien a procesului de rezolvare a unei probleme, adaug un plus de


complexitate oricrei probleme. Neasumndu-se acest plus de complexitate, putem uor compromite
procesul de realizare a unui sistem soft (=soluia executabil pe un calculator real a unei probleme date).
Un management bun are de rezolvat probleme de procurare i alocare optim a resurselor, comunicare
ntre partenerii de proiect (=specialitii n IS, beneficiarii, utilizatorii), lansare cu succes pe pia (dac
este cazul), etc. Nu a sftui pe nici un specialist n IS s considere normal o afirmaie de genul: Dac
cele spuse la punctul 2 sunt tratate cu maximum de seriozitate i competen, 1 i 3 nu mai nseamn
mare lucru. ndeosebi n cazul proiectelor mari, s-a dovedit, de nenumrate ori, neadevrul unei astfel
de afirmaii.

de asemenea, creterea

n IS, complexitatea problemelor nu este un accident; mai mult, putem spune c este legitim s ne
ateptm la elemente de complexitate chiar i acolo unde s-ar prea c acestea sunt lips. Dac mai
amintim cititorului observaia tendenioas, potrivit creia complexitatea de calitate se ntemeiaz pe
simplitate, acesta nelege mai bine insistena cu care prezint implicaiile complexitii unei probleme asupra
calitii soluiei acestei probleme. Calitate? Complexitate3? Complexitate de calitate? Multe se mai pot spune.
Specialistul n IS dorete s tie cteva lucruri simple:

Care sunt primejdiile?


Care sunt exigenele?
Cum se poate evita un eec?, etc.

Astfel de ntrebri, ne vom pune, ntr-o form sau alta i n aceast lucrare de iniiere n programarea
orientat pe obiecte i le putei gsi reluate n crile Iniiere n ingineria sistemelor soft i Iniiere n
modelarea obiect orientat a sistemelor soft utiliznd UML, scrise de D. Bocu i aprute la Editura
Albastr.
Nevoia presant de a cuta, permanent, rspunsuri noi la astfel de ntrebri, justific avalana de nouti
care caracterizeaz i lumea limbajelor de modelare, specifice ingineriei softului.

Orice exerciiu de modelare urmrete, indi ferent de acuitatea mijloacelor de investigaie, un anumit mod de organizare a complexitii
sistemului modelat.

1.2 Ce se nelege prin orientarea pe obiecte?


S-au scris destule cri pe tema orientrii spre obiecte. i mai multe sunt, probabil, articolele din
revistele de specialitate. Unele, foarte convingtoare. Altele mai puin. Nu cred c voi umple, brusc, golul care
mai exist, nc, n limba romn, scriind aceast carte. Dar voi ncerca s fac neles modul de gndire al unui
specialist n IS, care vede realitatea informaional n termeni specifici orientrii spre obiecte.
Orice sistem informaional 4 este mai uor de neles dac avem elemente suficiente referitoare la
datele vehiculate n sistem, procedeele de prelucrare (vehiculare) a datelor din sistem, interfeele sistemului
cu mediul n care acesta opereaz. Fiecare dintre elementele specificate mai sus are reguli proprii de organizare
i fiinare. n plus, mai exist i relaiile strnse dintre aceste elemente. De fapt, ntreaga istorie a IS se nvrte n
jurul ecuaiei prezentat n Figura 1.

<Soluia unei probleme>

= <Organizarea datelor>
+ <Organizarea prelucrrilor>
+ <Optimizarea interfeelor>

Figura 1. Ecuaia general a soluiei unei probleme n IS.


Ecuaia de mai sus a primit de-a lungul timpului numeroase rezolvri.
*
nainte de a descrie tipurile fundamentale de rezolvri, voi efectua o scurt trecere n revist a
vocabularului IS, esenial n comunicarea dintre partenerii unui proiect de dezvoltare a unui sistem soft.
Prin urmare, o firm productoare de soft produce i livreaz produse i servicii care se adreseaz
nevoilor i cerinelor clienilor. Cerinele clienilor constitue un exemplu de problem cu care trebuie s se
confrunte echipa de dezvoltare. Produsele i serviciile care satisfac aceste cerine pot fi considerate ca fiind
soluii. Pentru a livra soluii valide (= de calitate, la pre de cost redus i n timp util) firmele trebuie s fac
permanent achiziie, comunicare (partajare) i utilizare de cunotine specifice referitoare la domeniul
problemei de rezolvat. Pentru a discrimina i comunica eficient informaiile necesare pentru rezolvarea unei
probleme, firmele folosesc tehnologii adecvate. O tehnologie este, n general vorbind, un instrument pe care
membrii echipei de dezvoltare trebuie s nvee s-o foloseasc la ntregul ei potenial.
Aadar, problema de rezolvat, la care se adaug necesitatea de a nva modul de utilizare a
tehnologiilor necesare n rezolvarea problemei, ne permit o imagine, nc optimist, asupra complexitii
efortului de realizare a unui sistem soft. Amplificarea acestei complexiti este motivul pentru care ntregul
efort de realizare a unui sistem soft este structurat sub forma unui proiect. n cadrul unui proiect se desfoar,
dup reguli precise, toate activitile necesare pentru a asigura succesul efortului de realizare a unui sistem soft.
Dou dintre dimensiunile eseniale pentru succesul unui proiect sunt limbajul de modelare folosit i tipul de
proces utilizat pentru a materializa fora limbajului de modelare. Despre toate acestea, mai multe aspecte la
cursul care i propune iniierea studenilor n ingineria sistemelor soft.
*
Revenind la ntrebarea de baz a acestui paragraf, s observm c, nc de la apariia primelor
calculatoare, a aprut o nou dilem n faa omenirii:
Cum putem nva calculatoarele s ne rezolve n mod optim problemele?
La nceput, cnd calculatoarele erau folosite exclusiv pentru rezolvarea unor probleme cu carater
tiinific, soluia era programarea n cod main. Dificultile de baz n rezolvare acestor tipuri de
probleme erau dou :elaborarea modelelor matematice i transpunerea lor n cod main. Mai ales
programarea n cod main, era un gen de exerciiu la care nu se ngrmdeau dect indivizi care manifestau
un interes ieit din comun pentru sistemele electronice de calcul din acea generaie. Apariia limbajelor de
asamblare a generat o relaxare a cortinei de fier instalat de codul main ntre calculatoare i marea
mas a curioilor. O relaxare asemntoare s-a produs i n ceea ce privete tipurile de probleme
abordabile cu ajutorul calculatoarelor. Era momentul n care intrau pe scen aplicaiile de gestiune, datorit
4

Ca i realitatea informaional, sistemul informaional desemneaz un ansamblu de resurse care optimizeaz fluxurile informaionale dintr un sistem gazd. Pentru o documentare mai atent invit cititorul s rsfoiasc atent o carte bun de ingineria softului.

apariiei memoriilor externe. Locul datelor simple ncepe s fie luat de date structurate i din ce n ce mai
voluminoase. Presiunea exercitat de cererea crescnd de aplicaii de gestiune a impus trecerea la limbajele
de nivel nalt i mediu. n paralel, cu deosebire n faa proiectelor uriae (controlul traficului aerian,
gestiunea tranzaciilor unor bnci, informatizarea tot mai multor activiti ale intreprinderilor industriale)
apare nevoia disciplinrii procesului de derulare a acesto r proiecte din faza de specificare a cerinelor,
trecnd prin faza de analiz, continund cu proiectarea soluiei i terminnd (grosier vorbind) cu
programarea.
De unde aceast nevoie de disciplinare? Foarte simplu, complexitatea problemelor (parc am mai
auzit undeva despre acest lucru) nu mai putea fi stpnit lucrnd fr metod. Astfel au aprut, de-a
lungul timpului, tot felul de mode n ceea ce privete abstractizarea soluiei i nu numai.
Managementul unui proiect trebuie s aib, permanent, n vizor, cel puin, asigurarea limbajului de
modelare adecvat i a modelului de dezvoltare optim 5. De la moda programelor-mamut (singura posibil n
vremea programrii n cod main) s-a ajuns treptat la nevoia modularizrii (= descompunerea problemei iniiale
n subprobleme, eventual aplicarea repetat a acestui procedeu, obinndu-se nite piese ale soluiei numite
module, care, asamblate, compuneau, n sfrit soluia). ntrebarea care a furnicat, ani la rnd, creierele
teoreticienilor i practicienilor, deopotriv, era:
Care sunt criteriile dup care se face modularizarea unei soluii?

DATE
Problem
(activitate-sistem
real al crui
comportament
trebuie modelat)

PRELUCRRI

Figura 2. Perspectiva clasic asupra relaiei dintre date i prelucrri n structura unei
soluii
Exist o serie de factori externi ai calitii unui sistem soft care in sub presiune tendina de a
modulariza de amorul artei, precum: corectitudinea, robusteea, reutilizabilitatea, portabilitatea, etc. Exist
i o serie de factori interni ai calitii unui sistem soft, care preseaz, n egal msur, precum: structurarea
soluiei, claritatea algoritmilor, calitatea arhitecturii, etc.
Meninerea n echilibru a acestor factori de presiune este o sarcin extrem de dificil. n cele din
urm, cercettorii au ajuns la concluzia c, din punct de vedere al celui care lucreaz, materializarea acestor
factori la parametri satisfctori sau marginalizarea lor, depind de decizia luat n ceea ce privete relaia
dintre date i prelucrri n procesul de modularizare a soluiei unei probl eme. Istoria ne arat c au existat
teoreticieni i practicieni ncredinati c singura metod de modularizare valid este modularizarea dirijat de
date (altfel spus, nainte de a te ocupa de organizarea prelucrrilor, rezolv, n mod optim, problema organizrii
datelor; din schema de organizare a acestora se va deriva i schema de structurare a prelucrrilor). Tot istoria ne
arat c au existat i teoreticieni i practicieni ncredinati c singura metod de modularizare valid este
modularizarea dirijat de prelucrri (altfel spus, ocup-te, mai nti, de organizarea prelucrrilor i, mai apoi,
f rost de datele necesare i organizeaz-le conform cerinelor prelucrrilor). Curnd s-a observat c dihotomia
date-prelucrri nu este benefic sub nici o form. A existat o soluie de compromis (modularizarea dirijat
de fluxurile de date), care s-a dovedit n timp nesatisfctoare n numeroase situaii din realitate. Din punct de
vedere al criticilor fundamentale care se pot formula la adresa acestor abordri esena este urmtoarea: Dac
soluia unei probleme nseamn ansamblul date-prelucrri, fiecare component avnd o existen relativ
autonom i reguli proprii de organizare, atunci avem situaia din Figura 2.

Mai multe detalii n aceast privin n cartea Iniiere n ingineria sistemelor soft, D. Bocu, Editura Albastr, Cluj-Napoca, 2002

Esenial n mesajul transmis de Figura 2 este faptul c datele sunt sficient de izolate de prelucrri
pentru ca o modificare n structura unei componente s dea uor peste cap structura celeilalte
componente.
Conform paradigmelor caracterizate n Figura 2, era posibil o caracterizare de tipul celei prezentate
pentru problema de mai jos.
Problema 1: S se realizeze un sistem soft care simuleaz deplasarea unui om pe o suprafa
plan.
Dac a fi un partizan al modularizrii dirijate de date, mai nti mi-a pune urmtoarele ntrebri: care
sunt atributele informaionale care caracterizeaz un om (stilizat convenabil, s spunem)?. Cum se caracterizeaz
un plan? Cum se memoreaz intern i extern datele despre aceste obiecte? Dup ce am distilat satisfctor
lumea datelor, ncep s m ocup i de lumea prelucrrilor necesare n jurul acestor date. Obin, inclusiv n
viziunea limbajelor de programare suport, dou lumi, care interfer, dar au reguli de organizare i reprezentare n
memorie distincte. Mai trist, legtura dintre date i prelucrri este o problem care se gestioneaz prin
programare, ca i cnd nu ar fi suficiente problemele celelalte. Ce ne facem, ns, dac apare necesitatea
simulrii deplasrii unei vieuitoare n genere, pe o suprafa plan? Pentru fiecare vieuitoare n parte iau
travaliul de la capt? Posibil, dar total contraindicat din multe puncte de vedere( pre de cost, extensibilitate,
ncadrare n termenele de execuie, etc.). Este limpede, reformulat ca mai sus, enunul problemei ne pune n faa
sarcinii de a modela comportamentul unor obiecte, heterogene ca tip, dar ntre care exist afiniti, att de natur
informaional ct i comportamental. Astfel apare, ceea ce n modelarea obiect orientat se numete problema
gestiunii similaritilor unor colecii de obiecte . Gestiunea corect a similaritilor unei colecii de obiecte,
heterogene din punct de
Soluia orientat pe obiecte a problemei
vedere al tipului definitor,
se realizeaz desfurnd n
paralel efort de clasificare
i, acolo unde este cazul,
ierarhizare cu ajutorul
C1
Problem
operaiilor
de
(activitate-sistem
generalizare / specializare.
real al crui
Cum arat lumea privit din
comportament
aceast
perspectiv?
trebuie modelat)
Simplificnd
intenionat,
C11
C12
cam ca n Figura 3.
Nu voi da, nc,
nici o definiie, dar voi face
o serie de observaii pe care
le
voi
aprofunda
n
capitolele urmtoare.

C111
C121

C122

Figura 3. Perspectiva orientat pe obiecte a soluiei unei probleme


1.

Se insinueaz faptul c soluia orientat pe obiecte a unei probleme se obine n urma unui demers de
organizare a unor obiecte, care au att proprieti informaionale ct i comportament (se manifest,
astfel, ntr-un cadru absolut natural, un mai vechi principiu utilizat n modelare i anume principiul
ncapsulrii datelor i prelucrrilor. ncapsulare facem i n Pascal, cnd scriem unit-uri care furnizeaz
anumite servicii unor categorii bine definite de utilizatori. Aceste unit-uri au interfa i implementare.

Manifestarea principiului ncapsulrii, n acest cadru, nsemna ascunderea detaliilor de


implementare fa de utilizatori, prin publicarea unei interfee stabile. O interfa este stabil dac utilizatorul
ei nu sesizeaz eventualele modificri aduse implementrii interfeei. 6
6

Manifestarea principiului ncapsulrii, n acest cadru, nsemna ascunderea detaliilor de


implementare fa de utilizatori, prin publicarea unei interfee stabile. O interfa este stabil dac utilizatorul
ei nu sesizeaz eventualele modificri aduse imple mentrii interfeei.

2.

n sfrit, aplicnd riguros principiul ncapsulrii, putem defini clase de obiecte care au o importan
esenial pentru maparea domeniului problemei peste domeniul soluiei. Exist, ns, numeroase alte
raiuni pentru care principiul ncapsulrii se aplic conjugat cu alt principiu important n modelarea
orientat pe obiecte: principiul motenirii. Aplicarea acestui principiu ne ajut s raionalizm
redundanele care apar, n mod inerent, n procesul de elaborare a unei soluii n genere . Mai
mult, principiul motenirii pregtete terenul pentru rezolvarea unor probleme interesante care in de
polimorfism i genericitate. Exemplul de referin n aceast privin este Java.

Fr a mai insista prea mult, s desprindem concluzia care se impune evident la acest nivel de
prezentare: Modelnd orientat pe obiecte, asigurm maximum de coresponden posibil ntre obiectele
care populeaz sistemul modelat i obiectele care dau, practic, via soluiei. Lucru absolut remarcabil,
deoarece principiul ncapsulrii (temelie a modularizrii de calitate n orientarea pe obiecte) introduce elemente
de stabilitate deosebit a soluiei chiar i n situaia n care apara modificri n sfera domeniului problemei.
Prpastia dintre date i prelucrri este nlocuit de reguli precise de asociere a datelor i
prelucrrilor, pentru a descrie tipuri de obiecte ntlnite n domeniul problemei i care sunt importante
pentru economia de resurse a soluiei.
Din aceast perspectiv privind lucrurile, este evident faptul c modelarea orientat pe obiecte este
altceva dect modelarea clasic (indiferent de nuan). Desluirea acestui altceva, la nivel de sintax,
semantic i pragmatic (prin raportare la un limbaj de programare) ne va preocupa n continuare. Cei
care se grbesc s abordeze i specificul modelrii orientate pe obiecte, abstracie fcnd de limbajele de
programare- suport pentru implementare, pot consulta lucrarea Iniiere n modelarea obiect orientat utiliznd
UML7.

D. Bocu, Editura Albastr, Cluj-Napoca

2 Concepte i principii n programarea orientat pe


obiecte
2.1 Concepte n programarea orientat pe obiecte
ncepnd cu acest capitol, orientarea pe obiecte va fi privit, nu de la nlimea preceptelor ingineriei
softului, ci din perspectiva programrii Java. Subliniez, nc odat, marea provocare pentru un programator
care ncearc fora unui limbaj n materie de obiect orientare nu este n sintax, semantica asociat
diferitelor tipuri de enunuri sintactice sau stilul de codificare, ci nsuirea spiritului orientrii pe obiecte
aa cum este el promovat de elementele suport ale limbajului.
De aceea, reamintesc cititorului contient faptul c va trebui s se ntrebuineze serios pentru a descifra,
dac mai este cazul, oferta limbajului C++ n ceea ce privete: tipurile fundamentale de date (similariti
remarcabile cu Java, dar i deosebiri, datorate n principal faptului c n C++ pointerii se manifest cu foarte
mult vigoare n cele mai neateptate contexte), reprezentarea structurilor de prelucrare (din nou, similariti
remarcabile ntre C++ i Java), operaiile I/O relative la consola sistem, din perspectiv C, precum i suportul C
pentru lucrul cu fluxuri, dac se dorete acest lucru. Nu voi spune dect urmtoarele: C++ este un superset al
limbajului C; compilatoarele de C++ sunt realizate astfel nct toate enunurile din C sunt acceptate, dar
ele recunosc i o varietate mare de enunuri specifice modului de lucru n orientarea pe obiecte .
Dup cum rezult din titlul acestui paragraf, n atenia mea se vor afla enunurile tipice programrii
orientate pe obiecte n Java.
nainte de a ajunge la aceste enunuri, trebuie s facem primii pai n nvarea spiritului orientrii pe
obiecte. Voi prezenta, n continuare conceptele fundamentale de care ne lovim frecvent cnd programm
orientat pe obiecte.
Spuneam n Capitolul 1 c, din perspectiv orientat pe obiecte, sistemul pe care l modelm va fi
ntotdeauna abstractizat de o colecie de tipuri de obiecte, ntre care exist anumite relaii. S ne imaginm, de
exemplu, c vrem s modelm lumea poligoanelor astfel nct s putem oferi suport pentru nvarea
asistat de calculator a proprietilor poligoanelor . Exist o mare diversitate de poligoane. Chiar i cele care
sunt de maxim interes din punct de vedere al predrii/nvrii n coal, sunt suficient de multe pentru a pune
probleme de abordare a prezentrii proprietilor lor. i n acest caz, ca n oricare altul, la nceput avem n faa
ochilor realitatea de modelat, care poate fi sau nu structurat dup legile ei naturale.
Pentru un individ cu pregtire matematic adecvat este evident c obiectele din Figura 4 sunt
clasificate aprioric. Eventual, putem spune c lipsesc unele tipuri de poligoane, pentru c inventarul fcut de noi
n Figura 4
este
incomplet.

Figura 4. Diferite tipuri de poligoane, aa cum se pot ntlni, n realitatea modelat, prin
reprezentani
Probleme noastr nu este de a stabili nite frontiere nuntrul crora s avem obiecte de acelai tip, ci de
a spune care sunt obiectele care nu ne intereseaz. Nu se ntmpl, ntotdeauna, aa. Exist probleme n care
efectiv trebuie s depunem eforturi pentru a clasifica obiectele.
Operaia de clasificare presupune identificarea unor categorii de obiecte, apelnd, simultan la
omiterea unor detalii, socotite nesemnificative, pentru a obine efectul de similaritate n procesul de
caracterizare a obiectelor.

Dac n atenia noastr se afl problema clasificrii poligoanelor, atunci, dac n caracterizarea unui
poligon reinem atribute precum: lista coordonatelor vrfurilor, definiia(), aria(), perimetrul(), atunci
rezultatul clasificrii este o clas de obiecte pe care o putem numi clasa Poligon. Astfel c putem da definiia de
mai jos.
Definiia 1 Se numete clas o colecie de obiecte care partajeaz aceeai list de atribute
informaionale i comportamentale.
Prin urmare, primul concept important cu care ne ntlnim n programarea orientat pe obiecte este
conceptul de clas. Rezolvarea orientat pe obiecte a unei probleme se bazeaz esenial pe abilitatea
specialistului (n cazul nostru programatorul) de a descoperi care sunt clasele pe baza crora se poate construi
soluia. Presupunnd c avem i noi aceast abilitate i, n acord cu criteriile proprii de clasificare (reflectate i n
inventarul din Figura 4), obinem urmtoarea colecie de clase candidate la obinerea soluiei problemei noastre.

Clasa patrulaterelor

Clasa triunghiurilor

Clasa hexagoanelor

Figura 5. Clasele candidate la obinerea soluiei pentru problema modelrii poligoanelor


Departe de mine ideea c am dat o soluie definitiv problemei clasificrii poligoanelor. Am prezentat,
ns, o soluie tributar unei anumite viziuni. n conformitate cu aceast viziune, singurele poligoane care
prezint interes pentru noi sunt triunghiurile, patrulaterele i romburile. Figura 5 ne atrage atenia, explicit,
asupra diversitii tipologice a patrulaterelor, fapt care evideniaz necesitatea recurgerii i la alt operator dect
clasificarea pentru a gestiona aceast diversitate. Situaia este, oarecum asemntoare i n cazul triunghiurilor,
dar nu am subliniat explicit acest lucru.
Fcnd abstracie de aceste elemente, deocamdat, s revenim asupra problemei care ne intereseaz cel
mai mult n acest moment: cum stabilim proprietile unei clase?
Regulile de baz n stabilirea proprietilor unei clase sunt urmtoarele:
Lista atributelor informaionale ale unei clase este, ntotdeauna, rezultatul unui compromis ntre
necesitatea unui maximum de informaii despre obiectele clasei respective (informaii, care, n
fond, caracterizeaz starea obiectelor din clasa respectiv) i necesitatea unui minimum de
redundane acceptate. Obiceiul unor programatori de a supradimensiona lista atributelor unei
clase pe motiv c mai bine s fie dect s le ducem lipsa, nu este un model de urmat, nici atunci
cnd exist memorie cu carul.
Odat specificate, atributele trebuie declarate ca fiind resurse private ale clasei, folosind
sintaxa specific limbajului pentru ascunderea unei resurse. Dogma orientrii pe obiecte n
legtur cu lista atributelor este c acestea sunt accesibile, diferitelor categorii de clieni, n
setare ca i n consultare, prin intermediul unor metode speciale de setare(numite i
modificatori) sau consultare(numite i selectori), crora li se mai adaug metode speciale

implicate n crearea obiectelor unei clase (constructorii), respectiv, eliminarea acestor obiecte
(destructorii). Evident, mai exist i alte tipuri uzuale de metode, precum iteratorii sau indexatorii,
crora li se acord o atenie special n C#.
Odat specificat lista atributelor informaionale se poate trece la specificarea listei operaiilor
clasei, list care abstractizeaz comportamentul clasei. n procesul de specificare a
comportamentului unei clase trebuie avute permanent n vedere cele dou dimensiuni ale
comportamentului unei clase: comportamentul reclamat de gestiunea strii obiectelor (crearea
lor, setarea valorilor atributelor, modificarea valorilor atributelor, consultarea valorilor atributelor,
distrugerea obiectelor) precum i comportamentul reclamat de relaia clasei n cauz cu alte
clase. Lista operaiilor unei clase, la nevoie, poate fi organizat, din punct de vedere al modului de
acces la aceste operaii. Un singur lucru este general valabil n aceast privin: faptul c orice
clas trebuie s afieze o list cu operaiile publice, care asigur accesul clienilor la serviciile
oferite de clas. Lista acestor operaii se numete, n mod normal, interfaa clasei.
Atenie, cititorule! Cnd specifici resursele unei clase, eti preocupat s spui ce fac obiectele clasei
respective, omind intenionat cum face clasa ceea ce trebuie s fac. Aadar, nu stric s facem
o distincie necesar ntre definirea unei clase (= specificarea atributelor i a operaiilor) i
implementarea clasei (= scrierea codului asociat operaiilor clasei). Definirea rspunde unor
comandamente externe (ce in de modul de utilizare a obiectelor clasei); implementarea rspunde
unor comandamente care in de intimitatea comportamentului obiectelor (mod de reprezentare n
memorie a obiectelor, mod de implementare a operaiilor n acest context). S mai adugm c o
operaie implementat se mai numete i metod.

Folosind notaia UML pentru reprezentarea vizual a proprietilor unei clase, avem situaia din Figura
6.
Un concept, inevitabil n programarea orientat pe obiecte este i conceptul de obiect. L-am folosit,
deja, la modul intuitiv, ca fiind o parte a unei realiti avnd o anumit valoare de ntrebuinare n contextul n
care apare. Acum este momentul s dm urmtoarea definiie.
Definiia 2. Se numete obiect o instan a unei clase.
De la teoria general a tipurilor de date, se tie c instana unui tip de dat este o variabil avnd o
anumit reprezentare n memorie, deci o identitate, i o anumit stare din punct de vedere al coninutului
memoriei asociate. n toate limbajele de programare, care ofer suport orientrii pe obiecte, clasa este asimilat
unui tip de dat (este drept un tip special), care devine folositor n momentul n care se manifest prin
intermediul instanelor. Instanele unei clase se vor numi, aadar, obiecte sau, uneori, variabile obiect.
Dogmatic vorbind, dac soluia unei probleme este modelat ca o singur clas, atunci ne ateptm ca
dinamica aplicaiei corespunztoare s fie opera comportamentului unei instane a clasei . Ce se ntmpl,
ns, dac soluia unei probleme este abstractizat de o ierarhie sau de o reea de clase? n acest caz, dinamica
aplicaiei este opera colaborrii ntre instaele unora dintre clasele ierarhiei sau reelei n cauz . Semantic
vorbind, modul n care colaboreaz mai multe obiecte pentru a rezolva o anumit problem, este greu de fixat
ntr-o formul definitiv. Din punct de vedere tehnic, ns, rezolvarea este relativ simpl, dup cum se poate
deduce i din Figura 7.
<Nume clas>
Lista atributelor informaionale,
specificate prin nume, tip i eventual
valoare implicit
Lista operaiilor, specificate prin
signatur

Figura 6. Notaia UML pentru o clas

Obiect

(Produs)
CodProd:112233

ListareFurn(CodProd)

(Furnizor)
AdresaListaFurn: XXXXXXXX

Clasa definitoare
a obiectului
Produs
char codprod[11];
:

void afisare();
:

Furnizor

ListaFurn *AdresaListaFurn;
:
ListareFurn(char codp[11])
:

Operaia afisare() apeleaz operaia ListareFurn()

Figura 7.Exemplu de comunicare(colaborare) ntre dou obiecte


Notaia UML8 pentru o clas i nelesul complet al noiunii de signatur9 pot fi urmrite, lund-o
naintea timpului, consultnd lucrarea [Iniiere n modelarea obiect orientat utilizn d UML, Dorin Bocu,
Editura Albastr, Cluj-Napoca, 2002]
n Figura 7 se prezint schema fundamental pentru colaborarea dintre obiecte. Unul dintre obiecte
(obiectul de tip Produs, n cazul nostru) iniiaz comunicarea cu cellalt obiect (de tip Furnizor, n cazul
nostru). Se mai obinuiete s se spun c obiectul de tip Produs i-a trimis un mesaj obiectului de tip Furnizor.
Este de ateptat ca, ntr-o form sau alta, mesajul s fie urmat de un rspuns. Aadar, dac OFurnizor este o
variabil de tip Furnizor i dac aceast variabil este accesibil unui obiect de tip Produs, atunci comunicarea
este posibil, cu condiia ca obiectil de tip Produs s cunoasc interfaa clasei definitoare a obiectului
OFurnizor i s aib acces la aceast interfa. n varianta cea mai simpl, un mesaj are structura:
<Obiect>.<Nume_metod>([<Lista_de parametri_actuali>]);
ceea ce ne ndreptete s dm definiia de mai jos.
Definiia 3. Se numete mesaj apelul unei metode a unui obiect, apel efectuat de ctre
potenial al obiectului n cauz.

un

client

Cunoaterea acestui fapt este deosebit de important n situaia n care vrem s explicm semantica
polimorfismului n programarea orientat pe obiect, ceea ce vom face n partea urmtoare a acestui capitol.
n sfrit, s mai menionez faptul c rspunsul pe care l d un obiect cnd primete un mesaj de la alt
obiect depinde de starea n care se afl obiectul care primete mesajul. Este un aspect asupra cruia
programatorul trebuie s fie atent, deoarece o stare improprie a obiectului destinatar, poate provoca
euarea iniiativei obiectului expeditor de a comunica. Multe excepii apar, n faza de testare a programelor,

UML-prescurtare de la Unified Modeling Language-Limbaj de modelare unificat, specificat de Rational Software Corporation i omologat
ca standard de facto de ctre grupul OMG
9
Signatura cuprinde, n genere: numele opreraiei, lista de parametri i, opional, tipul returnat

tocmai pentru c nu s-a manifestat suficient preocupare pentru evitarea utilizrii obiectelor atunci cnd acestea
sunt ntr-o stare critic (referine nerezolvate, resurse necesare insuficiente, etc.).
Fie, n continuare, definiia conceptului de stare.
Definiia 4. Se numete stare a unui obiect o abstractizare a valorilor atributelor acelui obiect
precum i a relaiilor pe care obiectul le are cu alte obiecte.
Aadar, recapitulnd, conceptele eseniale cu care operm n lumea orientrii pe obiecte sunt: clas,
obiect, stare obiect, mesaj.

2.2 Principii n programarea orientat pe obiecte


Am vzut n paragraful 2.1 care sunt conceptele cele mai importante cu care ne ntlnim n programarea
orientat pe obiecte. Se tie de la alte discipline exacte c, fr principii de utilizare a lor, conceptele sunt bune
doar de pus n raft, ca nite bibelouri cu care putem aminti posteritii de o lume disprut. Conceptele prind
via, cu adevrat, doar n momentul n care sunt acompaniate de un set de principii care fixeaz regulile
eseniale de utilizare a conceptelor. Evident, vom vedea care sunt aceste principii. Ce ne mai ateapt dincolo de
ele? Ne ateapt invitaia de a proba singuri valabilitatea acestor principii, la nceput, improviznd cu
inerent stngcie, mai apoi descoperind adevrate abloane de rezolvare a unor probleme tip. Ne st la
dispoziie, n cantiti industriale, n internet, experiena tuturor celor care i-au fcut o religie din orientarea pe
obiecte i au realizat aplicaii de referin n acest spirit. Voi prezenta, n continuare, principiile pe care le
consider absolut necesare pentru a programa n spiritul orientrii pe obiecte.
Abstractizarea
Obinuiesc s insist pe importana acestui principiu deoarece mnuirea lui fr inspiraia necesar (iar
inspiraia, ntr-un domeniu, are cunoaterea acelui domeniu ca naintemergtor) poate pune lesne sub semnul
ntrebrii calitatea unei soluii.
Abstractizarea este procesul de ignorare intenionat a detaliilor nesemnificative i de reinere a
proprietilor definitorii ale unei entiti.
Prin urmare, din perspectiv procesual, abstractizarea este o modalitate de a reflecta asupra
proprietilor unei entiti, cu scopul de a obine reprezentri care descriu comportamentul entitii, reprezentri
care pot ndeplini simultan funcii explicative, funcii modelatoare i, de ce nu, funii demiurgice, la diferite
paliere de profunzime. Utilitatea unei abstracii se manifest atunci cnd apar beneficiari n sfera ei de
manifestare. Ca un exemplu, referindu-ne la limbajele de programare, putem observa c, toate limbajele ofer
suport specific pentru abstractizare. Cu ct suportul pentru abstractizare este mai consistent, cu att putem spune
c avem de-a face cu un limbaj de programare de nivel mai nalt. In cazul limbajelor de programare,
abstractizarea nseamn un anumit gen de apropiere de limbajul uman i, prin aceasta, de gndirea uman.
De asemenea, la nivelul limbajelor de programare vorbim despre trei tipuri fundamentale de abstracii,
ca rezultate ale procesului de abstractizare: abstraciile procedurale, abstraciile la nivelul datelor i clasele.
Abstraciile procedurale sunt cel mai mult folosite n programare. Utilizarea lor metodic permite
ignorarea detaliilor legate de desfurarea proceselor. Toate funciile puse la dispoziia programatorilor n C prin
intermediului sistemului de fiiere antet sunt exemple de abstracii procedurale, a cror utilizare este uor de
nvat dac le cunoatem: numele, eventual lista de parametri i/sau tipul returnat, plus semantica operaiilor
realizate de respectivele abstracii. Nu trebuie s avem, neaprat, informaii despre implementarea acestor
funcii. Care este ctigul? Se creaz, la un anumit nivel de abstractizare a unui program, posibilitatea ca acesta
s fie exprimat ca o succesiune de operaii logice i nu n termeni de instruciuni primare ale limbajului. Pentru
lizibilitatea programului i, n consecin, pentru depanare, aa ceva este de maxim interes.
Abstraciile la nivelul datelor permit, de asemenea, ignorarea detaliilor legate de reprezentarea unui
tip de date, n beneficiul utilizatorilor tipului de date. Un exemplu remarcabil de astfel de abstracie la nivelul
datelor este tipul variant, specificat de cei de la firma Borland n cadrul limbajului Object Pascal. Cei care au
realizat aplicaii Delphi i au dat cu nasul peste tipul variant au probabil amintiri plcute despre versatilitatea
i uurina n utilizare a acestui tip de dat.
Clasele ca abstracii combin ntr-o nou abstracie, extrem de puternic i polivalent semantic, cele
dou abstracii mai sus pomenite, care in de acea epoc din istoria programrii n care deviza era:
Algoritmi+structuri de date=programe. Arsenalul pus la dispoziia programatorului de clase, n calitate de
instrumente de abstractizare va fi n atenia acestui curs, n continuare.

ncapsularea
Principiul ncapsulrii insist pe separarea informaiilor de manipulare a unei entiti de aspectele
implementaionale. Se deduce, cu uurin, faptul c ncapsularea este o varietate de abstractizare. Practicat
metodic i cu suport sintactic adecvat, n programarea orientat pe obiecte, ncapsularea este susinut i la alte
nivele, de ctre limbaje de programare diferite. De exemplu, conceptul de unit din Object Pascal, permite
ncapsularea resurselor unei aplicaii Delphi, ceea ce, n fond, nseamn modularizare, la un nivel de
abstractizare mai nalt dect cel specific ncapsulrii la nivel de clase. Cuvintele cheie pe care se sprijin
operaionalizarea principiului ncapsulrii sunt interfaa i implementarea. Motivul pentru care se insist att
pe acest principiu este simplu: separnd interfaa de implementare i admind c interfaa este foarte bine
structurat (rezult c este stabil n timp i acceptat de utilizatori din punct de vedere al utilitii i
comoditii n utilizare) nseamn c eventuale modificri ale implementrii (absolut fireti n condiiile
mbuntirii permanente a mediilor de execuie i programare) nu vor putea afecta utilizatorii.
Este bine ca cititorul s fac distincie ntre ncapsulare i localizarea datelor i a funciilor, n
cadrul aceleeai entiti. ncapsularea are nevoie de localizare pentru a sublinia caracterul de black-box al
entitilor, dar ea nseamn mult mai mult dect att. De asemenea, nu trebuie s fetiizm ncapsularea,
ateptnd de la ea s garanteze sigurana n procesul de manipulare a obiectelor. Ct de sigur n utilizare este un
sistem soft, hotrte programatorul, care combin eficient fora principiului ncapsulrii cu procedeele
tehnice de asigurare a proteciei fa de ingerinele cu efecte negative.
Aadar, din perspectiva ncapsulrii, o clas, indiferent de limbajul n care va fi implementat, trebuie s
aib, obligatoriu, dou compartimente, ca n Figura 8.

Student

Date i operaii private

(Implementarea)

Operaii publice

(Interfaa)

Figura 7. Componentele obligatorii ale unei clase, din perspectiva ncapsulrii


Motenirea
Mult vreme, motenirea a fost un vis pentru a crui ndeplinire, ntr-o form destul de primitiv,
programatorii trebuiau s depun eforturi intense. Apariia limbajelor care ofer suport sintactic pentru
operaionalizarea principiilor orientrii pe obiecte (OO), a confirmat, printre altele i marea importan a
principiului motenirii pentru specificul unei soluii OO. Din perspectiv mecanic privind lucrurile, acest
principiu afirm posibilitatea ca o clas B s moteneasc o parte dintre proprietile unei clase A. n acest
fel avem la dispoziie un mecanism practic pentru gestiunea similaritilor, naturale, de altfel ntr-o societate de
obiecte foarte diversificat. n paragraful 2.1 (Figura 4) am prezentat, deja, un exemplu de societate posibil de
obiecte, n care diversitatea punea probleme de clasificare, lsnd deschis problema gestiunii similaritilor, n
cazul mulimii patrulaterelor. Mergnd pe linia utilizrii notaiei UML pentru reprezentarea unei soluii OO,
atunci trebuie s spunem c dac avem o clas B care motenete o parte dintre proprietile clasei A, acest lucru
va fi redat grafic n felul n care este artat n Figura 9.

Simbolul care indic


relaia de generalizare
dintre clasele A i B

GENERALIZARE

SPECIALIZARE

Clasa printe, superclasa,


clasa de baz

Clasa copil, subclasa,


clasa derivat

Figura 8. O parte din semantica relaiei de motenire care opereaz ntre clase
Dup cum se vede, relaia de motenire nu este doar o relaie al crei neles se reduce la posibilitatea ca
B s moteneasc o parte din proprietile lui A; semantica relaiei de motenire este mult mai subtil.
Mai nti, este vorba despre necesitatea de a reflecta cu ndemnarea necesar la cele dou posibiliti
de a identifica o astfel de relaie: procednd top-down sau bottom-up, deci specializnd, dup ce am identificat
o clas rdcin, sau generaliznd, dup ce am terminat operaia de clasificare a claselor i am nceput s
organizm clasele n familii, dup similaritile care le leag. Indiferent de abordare, rezultatul trebuie s fie
acelai: o ierarhie de clase, n care similaritile sunt distribuite pe nivele de abstractizare, reducnd astfel la
minimum redundanele i pregtind terenul pentru o reutilizare elegant a codului i pentru o serie de alte
avantaje care nsoesc un lan de derivare. Exemplificm cu ierarhia din Figura 10, a crei semantic ne este deja
cunoscut.
n Figura 10 regsim aproape toate elementele specifice unei soluii obiect orientate, care folosete
judicios principiul motenirii. Astfel, aproape toate soluiile orientate pe obiect au o clas rdcin (care, n
anumite situaii poate fi o clas abstract, adic o clas care nu poate avea instane directe, dar referine avnd
tipul ei pot fi asociate cu instane ale descendenilor), dac soluia se reduce la o singir ierarhie de clase. n
ierarhie putem ntlni i clase intermediare, precum i clase terminale sau frunz.
Poligon

Triunghi

Clas rdcin,
poate fi i
abstract

Patrulater

Paralelogram

Trapez

Clas
intermediar

Patrulater
inscriptibil

Clase frunz
Romb

Dreptunghi

Figura 9. Principiul motenirii n aciune

Din punctul de vedere al programatorului, pe lng utilitatea motenirii n procesul de gestiune a


similaritilor, mai exist un avantaj care poate fi exploatat n faza de implementare a soluiei, avantaj derivat din
principiul motenirii sub forma unui alt principiu care afirm c:
Orice printe poate fi substituit de oricare dintre descendeni
Acest principiu este de mare utilitate pentru programatori, el fiind operaionalizat prin intermediul
operaie de casting, aplicat obiectelor ale cror clase definitoare sunt n relaie de motenire. Evident, este
vorba de un casting implicit n lumea obiectelor (descendentul motenind tot ceea ce se poate de la strmoi, va
putea opera n locul strmoului). Castingul de acest tip se numete up-casting. Se practic, explicit i downcastingul, dar programatorul trebuie s fie pregtit s rspund de consecine. ntr-un down-casting, este posibil
ca obiectul de tip strmo, convertit la un obiect de tip descendent, s nu asigure coerena informaional de care
are nevoie descendentul, deci pot apare, principial, excepii. n Java se ntlnesc amndou tipurile de casting.
n sfrit, n Figura 10 avem un exemplu de utilizare a motenirii simple, potrivit creia un descendent
poate avea un singur strmo. Unele limbaje de programare(C++, de exemplu) accept i motenirea multipl,
ceea ce nseamn c o clas poate avea doi sau mai muli strmoi. O astfel de soluie pentru principiul
motenirii este plin de riscuri, cu toate avantajele pe care le presupune. Motenirea multipl poate genera
ambiguiti care pot pune la ncercare rbdarea programatorului.

D
Figura 10. Exemplu de motenire multipl
n exemplul din Figura 11, clasa D are ca strmoi clasele B i C. Obiectele clasei D vor avea motenite
resursele lui A, att pe traseul lui B ct i pe traseul lui C. Ambiguitatea referirii la o resurs a lui A n cadrul
unei instane a lui D este evident. Cnd este considerat strict necesar, motenirea multipl se utilizeaz cu
discernmnt. Java i C# nu mai promoveaz motenirea multipl, propunnd alte soluii la aceast problem.
Motenirea nu este doar o problem de sintax, ci este esena nsi a programrii orientate pe obiecte.
Pe temeiul motenirii are rost s vorbim n continuare de principiul polimorfismului, aplicat la lumea obiectelor.
Polimorfismul
Dup cum se vede i n exemplul prezentat n Figura 10, ierarhia de clase care modeleaz, la urma
urmei, comportamentul unei aplicaii poate avea mai multe clase frunz, deci clase care pote genera instane.
Crearea unei instane este, indicutabil o problem n care programatorul trebuie s se implice, el trebuind s
stabileasc, n funcie de dinamica aplicaiei, ce constructor va coopera la crearea unei instane. n ideea c avem
o aplicaie care se ocup de simularea nvrii poligoanelor, vi se pare interesant s declarm cte o variabil
pentru fiecare tip de poligon din ierarhia prezentat n Figura 10 (mai puin clasa rdcin)? Nu este interesant
din dou motive:
1.
2.

Explozia de variabile obiect nu este un indiciu de performan n programare.


Odat create obiectele, programatorul trebuie s tie n orice moment ce fel de obiect lucreaz
la un moment dat. Chiar c a ceva poate deveni suprtor ntr-o aplicaie de mare
complexitate.

Nu ar fi mai civilizat s declarm o variabil de tip Poligon n care s pstrm instane create cu
ajutorul constructorilor oricror descendeni care pot avea urmai direci? Admind c, n clasa Poligon, am
declarat o operaie calculArie() care este suprascris n fiecare descendent, atunci situaia creat este urmtoarea:

obiectul creat cu ajutorul constructorului unui descendent al clasei Poligon i pstrat ntr-o variabil de tip
Poligon (principiul substituiei ngduie acest lucru), s-i spunem p, va putea s apeleze diferite implementri ale
operaiei calculArie(), n funcie de contextul n care se creaz p. Aadar, un mesaj de tipul p.calculArie() ce
rspuns va genera? Rspunsul va fi dependent de context, controlul contextului (adic alegerea metodei specifice
clasei definitoare a obiectului pstrat n p) realizndu-se de ctre sistem prin mecanisme specifice, n timpul
execuiei programului. Acest mod de legare a unui nume de operaie de codul metodei specifice tipului definitor
al variabile obiect gazd se numete late binding. Este un mod de legare mai puin performant dect legarea
static (la compilare), dar avantajele scuz dezavantajele insignifiante, n condiiile n care viteza procesoarelor
i disponibilul de RAM sunt n expansiune permanent.
S-a neles, probabil, faptul c polimorfismul este de neconceput fr motenire n care specializarea
claselor s se bazeze i pe suprascrierea unor metode n clase aflate n relaie de motenire. Tot ceea ce trebuie s
tie programatorul de aici ncolo este avertismentul c:
Motenirea i polimorfismul sunt ideale ca uz i contraindicate ca abuz.
Terminnd excursia n lumea conceptelor i a principiilor programrii orientate pe obiecte, nu ne
rmne dect s anunm c n capitolele urmtoare vom ncerca s vedem aceste abstracii la lucru n context
Java.

3 Specificarea i implementarea unei clase din


perspectiv Java
3.1 n loc de introducere
Fr s am pretenia c am epuizat semantica modelrii orientate pe obiect, n capitolele precedente, n
acest capitol voi ncepe incursiunea n lumea elementelor suport oferite de Java pentru implementarea orientat
pe obiect a modelelor obiect orientate.
Laboratoarele de cercetare i lumea practicienilor vd, nc, n acest limbaj un moment de referin n
zbuciumata evoluie a limbajelor de programare. Apariia limbajului C# la orizont, prin bunvoina celor de la
Microsoft, se anun un concurent redutabil, care, i propune s ctige, deopotriv, atenia fanilor Java i C++.
Pn ce apele se vor limpezi, m voi ocupa de ceea ce, tocmai, am anunat n lista subiectelor care fac obiectul
acestui capitol.

3.2 Atenie la importana efortului de abstractizare!


Voi ncerca s art cum se specific i implementeaz clasele n Java. n tot acest timp, ncercai,
mpreun cu mine, s nu minimalizai nici o clip importana hotrtoare a abstractizrii n elaborarea unor
soluii stabile i flexibile 10.
n acest scop voi considera un exemplu pretext de problem prin intermediul creia voi ncerca s pun
n valoare puterea de reprezentare a limbajului Java.
S se scrie codul Java care pune la dispoziia unor utilizatori poteniali capabiliti de lucru cu
liste simplu nlnuite de numere ntregi, pentru care resursele necesare reprezentrii sunt alocate
dinamic. n continuare m voi referi la aceast problem cu acronimul LSI.
De ce numai acest tip de list? De ce doar numere ntregi? Pentru c aa cere utilizatorul n acest
moment. Nici mai mult, nici mai puin. Aa se ntmpl i n viaa de toate zilele. Specialitii n IS trebuie s
livreze beneficiarilor ceea ce acetia se ateapt s primeasc . Amorul artei sau dispreul fa de beneficiar,
sunt taxate necrutor de ctre ansamblul regulilor jocului din industria de soft.
Nu voi exagera cu descrierea travaliului conceptual n urma cruia am ajuns la nite concluzii n
legtur cu rezolvarea problemei LSI. Dar, cteva elemente de descriere a atmosferei trebuie, totui precizate.
Se tie c structurile dinamice de date sunt preferate structurilor statice de date, atunci cnd
utilizarea chibzuit a memoriei i flexibilitatea relaiilor dintre obiectele care populeaz structura sunt
critice pentru calitatea unui sistem soft.
Se mai tie, totodat, c o structur dinamic de date este complet specificat dac am clarificat:

Tipul datelor care populeaz structura.


Mecanismul de nlnuire a datelor din structur.
Punctele de intrare n structur.
Operaiile cu ajutorul crora ntreinem i consultm structura.

Fiecare din cerintele de mai sus, poate face obiectul unor consideraii cu implicaii interesante asupra
soluiei. M limitez doar la a observa faptul c o structur de date dinamic este un exemplu reprezentativ
de tip de dat care poate fi modelat orientat pe obiecte, n a fel nct serviciile oferite s fie complete i
uor de apelat.
Intrnd puin n domeniul problemei, dac ne gndim la o list simplu nlnuit, semantica ei poate fi
vizualizat, parial, ca n Figura 12.

10

Nu este o contradicie ntre termeni. Cele mai bune modele, ntr -o lume care nu st pe loc, sunt modelele care pot fi socotite, n acelai
timp, nchise i deschise, deci stabile i flexibile.

Adresa de start a primului nod


Data_ 1

Data_2

Informae
nod
Legtura spre urmtorul nod

Data_n

Ultimul nod nu are un succesor

Figura 11. Incercare de vizualizare a unei liste simplu nlnuite

Prin urmare, obiectele care fac parte din inventarul problemei sunt: Nod (avnd ca proprieti informaionale
Data i Adresa de legtur cu urmtorul element iar ca proprieti comportamentale, cel puin operaii legate de
crearea unui nod i consultarea proprietilor lui informaionale) i Lista (un obiect care, n principiu este o
agregare 11 de obiecte de tip Nod).
Un obiect care poart marca tipului Lista va avea, aadar, proprieti informaionale i comportament
specific. Abstractiznd cu nverunare, lista proprietilor informaionale ale unui obiect de tip Lista ar putea s
conin doar adresa primului nod din list. ns, dac trecem n revist exigenele clienilor fa de un obiect de
tip Lista, vom descoperi c este indicat s avem un atribut pentru a indica dac lista conine sau nu elemente (un
exemplu de redundan n procesul de utilizare a memoriei interne care asigur o vitez sporit n procesul de
utilizare a unei liste). Dac acest atribut este un ntreg care indic chiar numrul elementelor din list, cu att mai
bine. Aadar, n notaie UML, n acest moment am putea avea situaia din Figura 13.

Lista
-Nod Astart;
-Nod AUltim;
-Int NrElem;

Nod
-Int Data;
-Nod Urmatorul;

+Nod(int Numar);
+void setareData(int Numar);
+int consultareData();
+void setareUrmator(Nod AUrm)
+Nod consultUrmator()

+void setareAStart(Nod Element);


+Nod consultaAStart();
+void setareNrElem(int ne);
+int consultaNrElem();
+setareAUltim(Nod Element)
+Nod consultaAUltim();
+void insereazaDNod(Nod Element);
+void insereazaINod(Nod Element);
+void stergeNodAdr(Nod Element);
+void stergeNodNum(int Nr);
+salveazaInFisier(char numef[]);
+incarcaDinFisier(char numef[]);)

Figura 12. Clasele candidate la rezolvarea problemei LSDI


Ce observaii putem face? Clasa Nod este o clas concret, adic, avnd constructor, poate avea
instane. S mai observm faptul c atributele clasei Nod sunt prefixate cu cte un semn -, ceea ce, n UML,
nseamn c sunt private. Conform dogmei OO, absolut normal. De asemenea, s mai observm c operaiile
11

In modelarea obiect orientat se folosete relaia de agregare pentru a indica o asociere ntre obiecte care, din punct de vedere semantic,
sunt ntr-o relaie parte-ntreg. Reprezentarea unei relaii de agregare este la latitudi nea programatorului.

clasei Nod sunt prefixate cu semnul + i sunt scrise cu font drept, ceea ce, n UML, nseamn c sunt publice i
au deja implementare valabil. Semantica acestei clase i a contextului n care opereaz s-ar prea c nu ne
pretinde specificarea unor operaii private sau protejate. Oare? Este adevrat c n Java, de exemplu, crearea unui
obiect de tip Nod se va face rezonabil, chiar i dac nu am prevedea un constructor, dat fiind faptul c obiectele
se creaz i n acest caz, atributele fiind iniializate cu valori predefinite (0 pentru numere, null pentru obiecte,
false pentru valori booleene, \u0000 pentru caractere). Dac un astfel de comportament implicit nu este de
acceptat, atunci este loc pentru a specifica operaii care fac validarea strii obiectelor. Aceste operaii ar putea fi
folosite, ca uz intern, de orice alt operaie care este sensibil la starea obiectului care o folosete la un moment
dat.
Pe de alt parte, observm faptul c unele dintre operaiile clasei Lista sunt scrise cu caractere italice. n
UML aceasta nseamn c aceste operaii sunt abstracte. Prin urmare, clasa Lista este o clas abstract, deci
nu are constructor i tipul introdus de aceast clas nu va putea avea instane directe. Pentru a fi util, clasa Lista
trebuie s aib descendeni. Care vor fi aceti descendeni? Vom considera c aceti descendeni sunt doi: o clas
care modeleaz o list simplu nlnuit de ntregi, n care cuvntul de ordine la creare este ordinea fizic
de introducere i o clas care modeleaz o list simplu nlnuit de ntregi, n care elementele listei sunt
introduse astfel nct, dup fiecare introducere acestea s fie n ordine cresctoare . Pe scurt: liste
indiferente la ordinea numerelor ntregi i liste sensibile la ordinea numerelor ntregi. Vom obine ierarhia din
Figura 14.
Lista

ListaOarecare

ListaSortata

Figura 13. Ierarhia claselor care modeleaz dou varieti de list simplu nlnuit.
Se poate observa c cele dou varieti posed operaiile necesare pentru a simula, n caz de nevoie i
comportamentul unei stive (AStart este Top-ul iar inserareINod() i stergeNodAdr(AStart) sunt operaiile
specifice unei stive, adic Push() i Pop()). Cititorul bnuiete c inserareINod() este abreviere de la inserare
nainte de nod iar inserareDNod() este abtreviere de la inserare dup nod.
Consideraii de acest gen i chiar mai profunde, trebuie s prilejuiasc orice ncercare de rezolvare
orientat pe obiect a unei probleme.
3.3 Specificarea i implementarea unei clase n Java
Este cunoscut faptul c, n Java, orice aplicaie este puternic obiect orientat, cel puin datorit cadrului
sintactic obligatoriu pentru realizarea unui applet sau a unei aplicaii Java obinuite. Dac spiritul orientrii pe
obiecte este bine neles, atunci Java este o soluie interesant pentru multe probleme a cror rezolvare presupune
realizarea unor aplicaii pentru care lumea Internet-ului este puternic deschis. Indiferent de tipul aplicaiei,
piesele de baz n realizarea acesteia sunt clasele. Vom avea, n cazul unei aplicaii Java obinuite, o singur
clas public, care conine funcia main() i una sau mai multe clase care modeleaz, la diferite nivele de
rafinare, comportamentul aplicaiei. De asemenea, n cazul unui applet Java, vom avea o singur clas public
care extinde clasa Applet i una sau mai multe clase care modeleaz, la diferite nivele de rafinare,
comportamentul applet-ului.
Privit de la cel mai nalt nivel de abstractizare, definiia unei clase n Java este:
[<List modificatori>] class <Nume clas> [extends <Clasa de baz>] [implements <Lista interfee>]
{
//List de resurse sau corp clas
}
Resursele unei clase sunt de dou tipuri: atribute i/sau operaii. Problema noastr, dup cum am vzut,
este de a organiza aceste resurse, astfel nct s putem beneficia de o serie de avantaje din punct de vedere
al efortului de dezvoltare ct i din punct de vedere al calitii softului 12.
12

Despre calitatea softului cititorul poate gsi elementele eseniale n D. Bocu, Iniiere n ingineria sistemelor soft, Editura Albastr, 2002

n paragraful 2.2 am vzut c o ncapsulare corect (n acord i cu dogma OO) nseamn s declarm ca
private atributele i s definim o interfa corespunztoare clasei. Vom vedea, mai jos, ce nseamn acest lucru
n cazul problemei noastre.
Atributele unei clase se specific sintactic astfel:
[<List modificatori atribut>] Tip <Lista identificatori variabile>;
Operaiile unei clase se specific prin signatur i implementare ca mai jos:
[<List_modificatori_operaie>]Tip_returnat Identificator_metod>
([<List parametri>) [throws <Lista excepii>]
{
<Corp operaie>
}
Formalizmul folosit pentru prezentarea sintaxei de definire a unei clase se bazeaz, dup cum se poate
deduce, pe urmtoarele convenii:
Orice construcie a utilizatorului este prezentat ntre simbolurile < ...>.
Orice construcie opional este ncadrat de simbolurile [...].
Cuvintele rezervate sunt evideniate prin ngroare.
ntrebarea fireasc care se pune este urmtoarea: la ce ne folosesc aceste elemente de variaie n
procesul de definire a unei clase.
Voi ncerca s rspund pe rnd la toate ramurile acestei intrebri.
Modificatorii aplicabili claselor
Dup cum se poate observa, cuvntul cheie class poate fi prefixat, opional, de un modificator. Lista
complet a acestor modificatori este: abstract, final, public.
Modificatorul de clas abstract
Java permite extinderea unei clase existente cu o subclas. Cu timpul, este posibil s v constituii
propriile biblioteci de clase care considerai c vor fi extinse de ali programatori. Pentru unele clase, poate s fie
inutil s implementai o operaie ct timp nu se cunoate cum va fi extins clasa. n astfel de cazuri, putei utiliza
cuvntul cheie abstract pentru a indica faptul c n descendeni toate operaiile clase trebuie s fie supradefinite
obligatoriu.
Clasa Lista din Figura 14 ar putea fi definit, prin urmare astfel, n Java:
abstract class Lista
{
private Nod AStart;
private Nod AUltim;
private int NrElem;
public void setareAStart(Nod Element);
public Nod consultaAStart();
public void setaretNrElem();
public int consultaNrElem();
public Nod consultaAUltim();
public abstract void insereazaDNod(Nod Element);
public abstract void insereazaINod(Nod Element);
public abstract void stergeNodAdr(Nod Element);
public abstract void stergeNodNum(int Nr);
public final void salveazaInFisier(char numef[]);
public final Nod incarcaDinFisier(char numef[]);)
}
Este evident faptul c descendenii ListaOarecare i ListaSortata sunt obligai s implementeze toate
operaiile clasei Lista, care sunt abstracte. De asemenea, s observm c implementarea definitiv a operaiilor
de salvare/restaurare a listei este realizat n clasa Lista i va fi folosit fr modificri n descendeni.
Modificatorul de clas final (tocmai l-am utilizat mai sus)

n general vorbind, Java permite unei clase s extind o alt clas. Atunci cnd definim o clas, n contextul
n care anticipm utilizarea ei, s-ar putea s nu dorim extinderea ei de ctre alte clase. n acest caz, prin
includerea cuvntului cheie final n cadrul definiiei clasei vom mpiedica crearea de subclase ale clasei n cauz.
Aadar, clasa:
public final class NumeClasa {...}
nu va putea s aib urmai.
Modificatorul de clas public
Atunci cnd utilizm cuvntul cheie public n cadrul declaraiei clasei, ne asigurm c acea clas este
vizibil / accesibil de oriunde. Dac dorim s controlm accesul la o clas, cuvntul cheie public nu are ce
cuta n declaraia clasei. S reamintim, totodat, faptul c Java permite o singur clas public ntr-un fiier cu
cod surs. Evident, caracterul public al unei clase poate avea alte conotaii n contextul organizrii codului surs
al unei aplicaii cu ajutorul pachetelor. Mai precis spus, o clas public poate fi utilizat din exteriorul pachetului
n care a fost declarat, pentru a crea instane sau pentru a o extinde. n schimb, o clas care nu a fost declarat
public este considerat o clasa friend , putnd fi accesat doar din interiorul pachetului n care este rezident.
Modificatorii aplicabili atributelor
Domeniul de valabilitate al unui atribut definete locaiile din program n care atributul este cunoscut.
n procesul de definire a unei clase putem controla domeniul unui atribut al clasei precednd declaraia lui cu
unul din cuvintele cheie: public, private, protected, static, final, tranzient, volatile. S menionm faptul c
un atribut care nu este nsoit de nici un modificator este vizibil friendly, adic doar din interiorul clasei i din
clasele din acelai pachet.
Modificatorul de atribut public
Un atribut public este vizibil / accesibil oriunde este vizibil / accesibil clasa care l conine. Aadar,
pentru a declara ca public un atribut vom proceda ca mai jos:
:
public int vizibilOriundeEsteVizibilaClasa;
:
Dogma spune c o clas care ajunge la client trebuie s-i ascund atributele fa de acesta, accesul la
ele fiind mijlocit de interfa, dac este cazul. Nu este, ns, exclus ca o serie de clase neterminale (care nu sunt,
deci clase frunz) s declare ca publice o parte a atributelor, protecia lor fiind controlat, la nivelul
descendenilor prin intermediul interfeelor sau al organizrii n pachete.
Modificatorul de atribut private
Un atribut privat este vizibil numai n interiorul clasei sale. Subclasele i clienii externi nu pot accesa
aceste atribute.
Modificatorul de atribut protected
Un atribut al clasei, declarat ca protejat, este accesibil n descendenii clasei sau n cadrul pachetului din
care face parte clasa deintoare. Atenie, un atribut declarat ca protected ntr-o clas va putea fi accesat n
scriere i citire n toi descendenii clasei n cauz, rezideni chiar i n afara pachetului gazd al clase care deine
atributul protejat. Nu va fi permis accesul direct la atributul protejat pentru clase care nu sunt descendei ai clasei
care declar atributul protejat.
Modificatorul de atribut static
Orice atribut care nu este declarat ca static este numit atribut de instan, ceea ce nseamn c fiecare
instan are propria copie a atributului. Atunci cnd este n interesul comportamentului clasei ca un atribut s fie
partajat de toate obiectele clasei n cauz, acel atribut va fi declarat ca static.
Modificatorul de atribut final
Atunci cnd n definiia unei clase menionm un atribut final, indicm compilatorului faptul c acel
atribut are valoare constant, care nu poate fi modificat de program. Iniializarea atributului cu o valoare se
poate face la crearea obiectlui gazd, prin contribuia constructorului sau n cadrul unei declaraii de tipul:
:
protected static final int nr=10;
:

Atenie! Cele dou metode de iniializare sunt mutual exclusive.


Modificatorul de atribut transient
Atunci cnd declarm un atribut ca fiind de tip transient, indicm compilatorului Java faptul c atributul
nu este o parte permanent a obiectului, deci de uz intern i n cazul serializrii, de exemplu, nu va fi salvat pe
memoria extern. Un atribut tranzient se declar astfel:
:
private transient String password;
:
Modificatorul de atribut volatile
Atunci cnd se compileaz programul, compilatorul analizeaz codul i, adeseori va efectua anumite
manevre cu scopul de a optimiza performanele codului. Atunci cnd dorim s scoatem un atribut de sub
incidena unei astfel de eventualiti, o declarm ca volatil. Practic, aceasta nseamn c exist situaii
particulare n care comunicaia cu alte programe sau rutine necesit neintervenia compilatorului asupra unui
atribut, esenial pentru buna desfurare a comunicaiei n cauz.
Modificatorii aplicabili operaiilor
n aceast seciune vom prezenat o serie de modificatori care, de cele mai multe ori, sunt aplicabili
metodelor care implementeaz operaiile claselor. Aceti modificatori sunt: public, private, protected, static,
final, abstract, native, synchronized.
Modificatorul de metod public
Semnificaia acestui modificator, n cazul n care se aplic unei metode, este asemntoare cu cea pe
care o are cnd se aplic unui atribut.
Modificatorul de metod private
Semnificaia acestui modificator, n cazul n care se aplic unei metode, este asemntoare cu cea pe
care o are cnd se aplic unui atribut.
Modificatorul de metod protected
Semnificaia acestui modificator, n cazul n care se aplic unei metode, este asemntoare cu cea pe
care o are cnd se aplic unui atribut.
Modificatorul de metod static
Semnificaia acestui modificator, n cazul n care se aplic unei metode, este, ntr-o oarecare msur,
asemntoare cu cea pe care o are cnd se aplic unui atribut. Mai precis, trebuie s spunem c o metod static,
pentru a fi utilizat nu reclam neaprat o instan, putnd fi utilizat i printr-un apel de tipul:
NumeleClasei. NumeleMetodeiStatice(parametri);
O metod static poate fi utilizat pentru a accesa ali membri statici ai clasei, dar, n nici un caz, pentru
a accesa variabile nestatice.
Modificatorul de metod final
Am vzut, deja, n cursul 2, c anumite metode ale claselor pot fi supradefinite n clasele descendente.
Dac, din variate motive, dorim s blocm posibilitatea supradefinirii unei metode, atunci vom informa
compilatorul de aceast intenie declarnd metoda ca final astfel:
public final void MetodaNuPoateFiSupradefinita();
Modificatorul de metod abstract
Dac o metod a unei clase este precedat de cuvntul cheie abstract, atunci compilatorul nu va
autoriza crearea de instane ale clasei n cauz. Totodat, o clas care extinde clasa n cauz va trebui s
implementeze metoda abstract obligatoriu. Declararea se face astfe:
public abstract void implementareUlterioar();
Atenie! O metod abstract nu poate fi privat sau final.

Semantica cuvntului cheie abstract (= metoda va fi implementat n descendeni) vine n contradicie


cu semantica cuvintelor cheie private i final care spun, n moduri diferite, c metoda nu poate fi modificat.
Modificatorul de metod native
Acest modificator se utilizeaz pentru a spune compilatorului c o anumit metod utilizeaz cod scris
ntr-un alt limbaj de programare, cum ar fi C/C++, de exemplu. Aceast posibilitate trebuie folosit cu
discernmnt deoarece lovete puternic n portabilitatea aplicaiei, aa cum este ea neleas n Java.
Modificatorul de metod synchronized
Se tie c Java ofer suport pentru multitasking sub forma un program mai multe fire de execuie.
n funcie de activitatea programului respectiv, uneori este necesar s garantm faptul c, dou sau mai multe fire
nu pot accesa simultan aceeai metod. Prin urmare, pentru a controla numrul de fire de execuie care pot
accesa o metod la un moment dat, utilizm cuvntul cheie synchronized. Atunci cnd compilatorul Java
ntlnete o metod prefixat de cuvntul cheie synchronized, introduce un cod special care blocheaz metoda
cnd un fir ncepe execuia instruciunilor metodei i o deblocheaz cnd firul i ncheie execuia. n mod uzual,
sincronizarea metodelor este reclamat de necesitatea partajrii datelor.
Am prezentat, mai sus, semantica cuvintelor cheie ascunse sub sintagma modificatori, aplicai
atributelor sau operaiilor.
Sintaxa care st la baza definirii unei clase mai conine, opional i cuvntul cheie extends pentru a
indica o clas de baz clasei n curs de definire.
De asemenea, n sintaxa prezentat se mai evoc i eventualitatea apariiei cuvntului cheie implements
urmat de numele interfeelor pe care le implementeaz clasa, atunci cnd este cazul. Evident, cuvntul cheie
extends este legat de problematica motenirii n programarea orientat pe obiecte n Java iar cuvntul cheie
implements este legat de problematica utilizrii interfeelor, pentru a introduce numeroase elemente de
flexibilitate n programarea Java, inclusiv rezolvarea motenirii multiple, neadmis direct n Java.
Despre aceste dou probleme vom discuta pe ndelete in Capitolul 5.
nainte de a trece la prezentarea cadrului C++ pentru definirea unei clase putem urmri, mai jos, codul Java
asociat definirii claselor Nod i Lista, aa cum apar ele n lumina observaiilor fcute pn acum.
//--------------------------------------------//Cod Java care demareaza procesul de rezolvare
//a problemei LSI
//--------------------------------------------//Specificare minimala a clasei Nod
//Implementare clasa Nod
class Nod
{
private int Data;
private Nod Urmatorul;
//constructor
public Nod(int Numar)
{
Data=Numar;
};
//modificator atribut Data
public void setareData(int nr)
{
Data=Numar;
};
//selector atribut Data
public int consultareData()
{
return Data;
};
//Modificator atribut Urmatorul
public void setUrmator(Nod Element)

{
Urmatorul=Element;
};
//Selector atribut Urmatorul
public Nod consultaUrmator()
{
return Urmatorul;
};
};
//Specificare aproape completa a clasei abstracte Lista
abstract class Lista
{
private Nod AStart;
private Nod AUltim;
private int NrElem;
//Modificator atribut AStart
public void setareAStart(Nod Element)
{
AStart=Element;
};
//Selector atribut AStart
public Nod consultaAStart()
{
return AStart;
};
//Modificator atribut NrElem
public void setareNrElem(int ne)
{
NrElem=ne;
};
//Selector atribut NrElem
public int consultaNrElem()
{
return NrElem;
};
//Modificator atribut AUltim
public void setareAUltim(Nod Element)
{
AUltim=Element;
};
//Selector atribut AUltim
public Nod consultaAUltim()
{
return AUltim;
};
//Metoda abstracta
//Va fi implementata in descendenti
//Insereaza un element dupa ultimul nod introdus
public abstract void insereazaDNod(Nod Element);
//Metoda abstracta

//Va fi implementata in descendenti


//Insereaza un element inaintea ultimului nod introdus
public abstract void insereazaINod(Nod Element);
//Metoda abstracta
//Va fi implementata in descendenti
//Sterge un element de adresa specificata
public abstract void stergeNodAdr(Nod Element);
//Metoda abstracta
//Va fi implementata in descendenti
//Insereaza un element de pozitie specificata
public abstract void stergeNodNum(int Nr);
//Metoda publica finala
//Deocamdata neimplementata
//Salveaza lista reperata de AStart
//intr-un fisier de nume specificat
public final void salveazaInFisier(char numef[])
{
System.out.println("Neimplementata...");
};
//Metoda publica finala
//Deocamdata neimplementata
//Restaureaza lista folosind informatiile din fisierul
//de nume specificat
public final Nod incarcaDinFisier(char numef[])
{
System.out.println("Neimplementata...");
return null;
};
}
Codul prezentat mai sus trebuie s fie extins i rafinat pentru a acoperi toate cerinele iniiale ale
problemei i pentru a face fa exigenelor de calitate fireti (modularizare corect, fiabilitate, extensibilitate,
etc.).

4 Motenirea n programarea orientat pe obiecte din


perspectiv Java
4.1 Scurt introducere
Am vzut, deja, faptul c unul dintre principiile importante n programarea orientat pe obiecte
este principiul motenirii. Aa cum se ntmpl, n general, cu principiile, nici principiul motenirii nu
trebuie fetiizat sau bagatelizat. Bagatelizarea lui nseamn, ceva de genul: Hai s facem motenire ca s ne
aflm n treab sau ca s vedem dac funcioneaz. Fetiizarea, din contr, ar nsemna Sfinte Sisoe, nimic mai
frumos i mai eficient dect aplicarea principiului motenirii la tot pasul.Ambele variante sunt false. Cum am
mai spus i alt dat, principiul motenirii este disponibil pentru uz, nu pentru abuz . Ceva mai concret spus:
Motenirea este o modalitate performant de reutilizare a codului, dar nu este ntotdeauna cel
mai bun instrument pentru ndeplinirea acestui obiectiv.
Dac este folosit necorespunztor, programele obinute vor fi destul de fragile.
Motenirea poate fi utilizat cu succes n cadrul unui pachet, unde implementrile subclaselor i
superclaselor sunt controlate de aceeai programatori. De asemenea, poate fi folosit la extinderea claselor
care au fost concepute i documentate exact n acest scop.
ns, motenirea unor clase concrete obinuite, n afara granielor unui pachet, poate fi periculoas.
Trebuie s subliniez faptul c toate consideraiile pe care le fac n acest paragraf se refer la motenirea
neleas ca motenire a implementrii (o clas extinde o alt clas, exprimndu-ne n spirit Java). Se tie,
desigur c relaia de motenire opereaz i n relaia dintre interfee, chestiune care nu cade sub incidena
observaiilor critice, de mai sus, la adresa motenirii.
Defeciunea esenial care poate apare cnd apelm la motenire se refer la faptul c, prin
motenire, ncapsularea are de suferit n mod natural.
i aceasta deoarece funcionarea corect a unei subclase depinde de detaliile de implementare ale
superclasei. Implementarea superclasei se poate modifica de la o versiune a programului la alta, situaie n care ,
subclasa este expus deteriorrii chiar i n cazul n care codul ei a rmas neatins. Prin urmare, subclasa este
obligat s evolueze odat cu superclasa, exceptnd, bineneles, situaia n care autorii superclasei au conceputo i documentat-o special pentru a fi extins.
O regul de bun sim n utilizarea principiului motenirii ne spune c este bine s folosim
motenirea numai dac subclasa este, ntr-adevr, un subtip al superclasei.
Altfel spus, o clas B trebuie s extind o clas A numai dac ntre cele dou clase exist o relaie
de tipul B este un A.
Cu referire la mulimea poligoanelor, prerea unor aa zii specialiti, conform creia putem deriva
clasa dreptunghi din clasa triunghi este complet n afara logicii relaiei de motenire. Nici n visul cel mai
frumos un dreptungi nu este un triunghi. n schimb, putem spune c triunghiul este un descendent al poligonului,
pe motiv c orice triunghi este un poligon, etc.
Concluzionnd, motenirea este un aspect important n programare, dar problematic, pentru c
poate fi aplicat denaturndu-i esena i pentru c ncalc, n mod natural, regulile ncapsulrii.
Motenirea se poate folosi eficient numai cnd ntre superclas i subclas exist o relaie real de genul
tip-subtip. Chiar i n acest caz, codul obinut poate fi fragil, avnd probleme cnd apar modificri i fiind
predispus la anumite bree n securitatea resurselor unei clase.
Evitarea unor astfel de probleme este posibil, n anumite situaii, prin utilizarea compunerii n locul
motenirii.
Relaia de compunere presupune ca n definiia unei clase A s apar i instane ale altor clase, ale
cror servicii urmeaz s fie utilizate de ctre clasa A. Pe de alt parte, este tot att de adevrat faptul c multe
probleme rezolvate n C++ cu ajutorul pointerilor, nu ar avea rezolvare echivalent semantic n Java, fr
suportul motenirii.

4.2 Motenirea n Java


Nu este cazul s revin asupra sintaxei operaiei de motenire n Java.
Java a optat pentru un cuvnt cheie pentru a informa compilatorul de intenia unei clase de a moteni
proprietile altei clase. Acest cuvnt cheie este extends. Ceea ce trebuie s semnalm ca important, pentru
spiritul motenirii n limbajul Java, este faptul c acesta nu ofer suport pentru motenirea multipl, n sensul
n care este aceasta neleas n alte limbaje. n Java, o clas poate avea o singur superclas. De aici rezult
posibilitatea teoretic de a construi doar ierarhii de clase, cu suportul oferit de motenirea cu extends. Dat fiind
faptul c n practic exist i nenumrate situaii n care semantica motenirii multiple se impune ca alternativa
cea mai valabil, Java ofer o porti pentru a simula motenirea multipl cu ajutorul interfeelor. Jongleriile care
se pot face cu ajutorul interfeelor au depit de mult inteniile iniiale ale specificatorilor limbajului Java. M
voi ocupa de acest subiect n paragraful 5.3.
Exemplul 4.1 ilustreaz motenirea, avnd ca idee cluzitoare specializarea clasei de baz prin
adugare de membri noi. De asemenea, Exemplul 5.1 ilustreaz i cele dou tipuri de casting posibile n
programarea orientat pe obiecte din Java. n esen, este vorba despre faptul c, avnd contextul din Figura 15,
sunt posibile dou tipuri de casting, principial deosebite.
A

Figura 14. Derivare pretext pentru dou tipuri de casting


Primul tip de casting este implicit. Este vorba despre conversia unei variabile obiect de tip B la o
variabil de tip A. Motivul pentru care acest tip de conversie este implicit este simplu: resursele lui A se
regsesc printre resursele lui B. Astfel c, atunci cnd B este coerent din punct de vedere al strii, nu exist
nici un motiv ca A s fie altfel, n urma conversiei.
Al doilea tip de casting necesit acordul explicit al programatorului pentru a fi efectuat i ntr-un anumit
sens, asumarea rspunderii pentru aceast conversie. Este vorba de conversia unei variabile obiect de tip A la o
variabil de tip B. De ce este necesar acordul? Foarte simplu: resursele lui A sunt incluse printre resursele
lui B. Conversia de mai sus este posibil s aduc variabila de tip B ntr-o stare improprie pentru utilizarea unor
metode, deoarece unele date membre pot rmne neiniializate adecvat. Cu toate acestea, down casting-ul este
esenial n programarea generic, asupra creia vom reveni ntr-un curs special.
Exemplul 4.1
//Clasa de baz
//Modeleaz informaional obiectul Fruct
//Potrivit abordrii din acest cod
//metoda consultaTipFruct() nu poate fi
//redefinit n descendeni
class Fruct
{
private int tipfruct;
Fruct(int t)
{
tipfruct=t;
System.out.println("Constructor Fruct...");
}
final int consultaTipFruct()
{
return tipfruct;
}
}

//Subclas a clasei Fruct


//Para este un fruct->este respectat spiritul natural
//al motenirii
//Se adaug noi atribute informaionale
//Se adaug metode specifice
//Este un exemplu clasic de specializare prin adaugare
class Para extends Fruct
{
private double greutate;
private int forma;
Para(int t,double g,int f)
{
super(t);
System.out.println("Constructor Para...");
greutate=g;
forma=f;
}
double consultaGreutate()
{
return greutate;
}
int consultaForma()
{
return forma;
}
}
//Subclas a clasei Fruct
//Portocala este un fruct->este respectat spiritul natural
//al motenirii
//Se adaug noi atribute informaionale
//Se adaug metode specifice
//Este un exemplu clasic de specializare prin adugare
class Portocala extends Fruct
{
private int tipcoaja;
Portocala(int tf,int tc)
{
super(tf);
System.out.println("Constructor Para...");
tipcoaja=tc;
}
int consultaTipCoaja()
{
return tipcoaja;
}
}
//Clasa care utilizeaz ierarhia de clase de mai sus
//Tipurile Para i Portocala au acelai supertip
//dar sunt incompatibile la atribuire
//deoarece sunt pri ale unor lanuri de derivare
//diferite
public class Mosten1
{
public static void main(String[] s)
{
//Declarare variabil referin

//avnd tipul clasei rdcin


Fruct of;
//Declarare i alocare variabil referin
//de tip Para
Para obpara=new Para(1,1.5,2);
//Declarare i alocare variabil referin
//de tip Portocala
Portocala obport=new Portocala(10,1);
//Utilizare normal a variabilei de tip Para
System.out.println("Para ..creata ca referinta Para");
System.out.println("Tip fruct:"+ obpara.consultaTipFruct());
System.out.println("Greutate fruct:"+obpara.consultaGreutate());
System.out.println("Forma fruct:"+obpara.consultaForma());
//Utilizare normala a variabilei de tip Portocala
System.out.println("Portocala creata ca referinta Portocala");
System.out.println("Tip fruct:"+obport.consultaTipFruct());
System.out.println("Tip coaja:"+obport.consultaTipCoaja());
//Exemplu de Up casting (implicit)
of=new Para(1,2.5,3);
//Exemplu de Down casting (explicit);
//Foarte util in programarea generica
obpara=(Para)of;
//Utilizare variabile referin
//setate prin casting explicit
System.out.println("Para ...creata ca referinta Fruct");
System.out.println("Tip fruct:"+obpara.consultaTipFruct());
System.out.println("Greutate fruct:" +obpara.consultaGreutate());
System.out.println("Forma fruct:"+obpara.consultaForma());
}
};
Exemplul 4.2 ilustreaz specializarea prin redefinirea metodelor, ca baz pentru comportamentul
polimorfic al obiectelor n Java. Mecanismul polimorfismului l voi pune n discuie n Capitolul 5.
Exemplul45.2
//Clasa de baza
//Modeleaz informional obiectul Fruct
//Metoda consultaTipFruct() se va redefini
//in descendentul Para
class Fruct
{
private int tipfruct;
Fruct(int t)
{
tipfruct=t;
System.out.println("Constructor Fruct...");
}
int consultaTipFruct()
{
return tipfruct;
}
}

//Subclas a clasei Fruct


//Para este un fruct->este respectat spiritul natural
//al motenirii
//Se adaug noi atribute informaionale
//Se redefinete metoda consultaTipFruct()
//Este un exemplu clasic de specializare prin redefinire
class Para extends Fruct
{
private double greutate;
private int forma;
Para(int t,double g,int f)
{
super(t);
System.out.println("Constructor Para...");
greutate=g;
forma=f;
}
int consultaTipFruct()
{
System.out.println("Consultare tip fruct..redefinire Para");
return super.consultaTipFruct();
}
double consultaGreutate()
{
return greutate;
}
int consultaForma()
{
return forma;
}
}
//Subclas a clasei Fruct
//Portocala este un fruct->este respectat spiritul natural
//al motenirii
//Se adaug noi atribute informaionale
//Se redefinete metoda consultaTipFruct()
//Este un exemplu clasic de specializare prin redefinire
class Portocala extends Fruct
{
private double greutate;
private int forma;
Portocala(int t,double g,int f)
{
super(t);
System.out.println("Constructor Portocala...");
greutate=g;
forma=f;
}
int consultaTipFruct()
{
System.out.println("Consultare tip fruct..redefinire Porto");
return super.consultaTipFruct();
}
double consultaGreutate()
{

return greutate;
}
int consultaForma()
{
return forma;
}
}
public class Mosten2
{
public static void main(String[] s)
{
//Declarare variabil referin de tipul clasei rdcin
Fruct of;
//Alocare referin utiliznd constructorul unei subclase
//a clasei rdcin (Para)
of=new Para(1,2.75,3);
System.out.println("Para ...creata ca referinta Fruct");
//Utilizare, de fapt, n spirit polimorfic
//a variabilei definite i alocate mai sus
System.out.println("Tip fruct:"+of.consultaTipFruct());
//Alocare referin utiliznd constructorul unei subclase
//a clasei rdcin (Portocala)
of=new Portocala(2,0.75,4);
System.out.println("Portocala ...creata ca referinta Fruct");
//Utilizare, de fapt, n spirit polimorfic
//a variabilei definite si alocate mai sus
System.out.println("Tip fruct:"+of.consultaTipFruct());
}
};

4.3 Motenirea multipl n Java


Dei o modalitate comod de a iei din impas n anumite situaii, motenirea multipl este criticat pentru
confuziile pe care le poate genera, dac este utilizat fr un efort de inventariere, adecvat focalizat asupra
proprietilor claselor candidate la calitatea de superclase pentru o clas derivat din ele. Duplicarea cmpurilor
i a metodelor, precum i violarea cras a ncapsulrii sunt principalele motive de ngrijorare cnd este vorba de
utilizarea motenirii multiple. Aadar, ne aflm n situaia din Figura 16.
Dac semantica din domeniul problemei impune o asemenea abordare, din punct de vedere conceptual,
atunci n Java soluia pentru posibilitatea de a spune despre C c este A sau B sau A i B o reprezint utilizarea
interfeelor. Interfaa este o varietate de clas, caracterizat prin faptul c poate declara metode abstracte i
publice i, dac este necesar, variabile care sunt considerate, implicit, de tip public, static i final, deci
constante. n foarte mare msur, comportamentul unei interfee este asemntor comportamentului unei clase.
Att de profund este
asemnarea
nct,
n
anumite situaii interfeele i
clasele se pot substitui
reciproc.
A
B

Figura 15.Motenirea multipl

Pentru a nelege modul de lucru cu interfeele consider eseniale urmtoarele precizri:


1. Mai nti trebuie s nvm cum se declar o interfa. Aceasta este o problem de sintax, mult mai
simpl dect problema conceptual, care trebuie clarificat nainte de a ajunge la sintax. Din punct de vedere
conceptual, tipul de raionament pe care l facem seamn cu cel pe care l facem cnd specificm o clas
abstract care are toate metodele virtuale pure, n C++ sau abstracte n Java. Din punct de vedere sintactic, avem
cadrul:
interface <Nume_interfa> [extends <List _de_interfee>]
{
<Signaturi de metode>
}
Se observ, deja, amnuntul care deosebete mecanica utilizrii claselor de mecanica utilizrii
interfeelor, anume, suportul pentru motenire multipl n cazul interfeelor. Pe acest amnunt se bazeaz
alternativa Java la motenirea multipl relativ la clase.
2. n al doilea rnd, utilizarea unei interfee este posibil, n mai multe moduri, dup ce am specificat i
implementat o clas care o utilizeaz. Ne amintim de sintaxa:
class <Nume_clas> [extends Nume_superclas] implements <List de interfee>
{
<Date membre>
<Funcii membre>
};
Dup cum se poate observa, o clas poate implementa mai multe interfee, depindu-se, astfel,
restricia Java n legtur cu motenirea multipl n relaia dintre clase. S mai subliniez i faptul c o clas care
implementeaz una sau mai multe interfee poate avea cel mult un strmo, eventual nici unul. Disciplina astfel
introdus este, sper, clar: metodele unei clase (care are, eventual un strmo) pot fi acoperitoare ca
specificare i implementare pentru listele de metode ale unor de interfee. n acest mod, avem la dispoziie
un mecanism de a vedea, din unghiuri diferite, ansamblul resurselor unei clase. Este clar c soluia Java
determin programatorii s mediteze mai atent nainte de a face jonciunea cu mai multe interfee.
3. Utilizarea efectiv a interfeelor este divers: ca tipuri definitoare pentru referine la obiecte, ca tipuri
implicate n casting, ca tipuri utile n programarea generic, etc. Cteva modaliti de utilizare a interfeelor se
pot vedea n Exemplul 4.3 i n Exemplul 4.4.
Exemplul4.3
//Interfata I1
//Expune functia f1()
interface I1
{
public void f1();
}
//Interfata I2
//Expune functia f2()
interface I2
{
public void f2();
};
//Interfata I12
//Extinde interfetele I1 si I2
//Exemplu de mostenire multipla
//a interfetelor
interface I12 extends I1,I2
{

public void f3();


}
//Clasa A implementeaza interfata I1
class A implements I1
{
public A()
{
System.out.println("AAAA...");
};
public void f1()
{
System.out.println("f1....");
};
};
//Clasa B implementeaza interfata I2
class B implements I2
{
public B()
{
System.out.println("BBBB...");
};
public void f2()
{
System.out.println("f2....");
};
};
//Clasa C implementeaza interftata I12
//Evident,functiile expuse de interfetele
//I1 si I2 sunt implementate si de catre
//clasa C
//Deoarece I12 este derivata din I1 si I2
//ni se ingaduie sa privim instantele de tip
//I12 ca fiind de tip I1 sau I2, dupa cum
//este in interesul nostru
class C implements I12
{
public C()
{
System.out.println("CCCC...");
};
public void f3()
{
System.out.println("f3...");
};
public void f1()
{
System.out.println("f1....");
};
public void f2()
{
System.out.println("f2....");
};
};

public class TestInterf


{

public static void main(String args[])


{
//Crearea unui obiect de tip I1
//utilizand clasa A
I1 ob1=new A();
System.out.println("Ura...");
//Utilizarea obiectului de tip I1
ob1.f1();
//Crearea unui obiect de tip I12
//utilizand clasa C
I12 ob12=new C();
//Utilizarea obiectului de tip I12
ob12.f1();
ob12.f2();
ob12.f3();
//Crearea unui obiect de tip I1
//utilizand clasa C
I1 ob2=new C();
//Utilizare obiect de tip I1
//creat cu suport C
ob2.f1();
//Down casting dirijat de
//interfete
ob2=(I1)ob12;
ob2.f1();
}
}

Exemplul 4.4
//Interfata IConst care declara
//doua constante si o metoda
interface IConst
{
int Numar=100;
String s="Bine ati venit!";
void ftest();
}
//A foloseste interfata IConst
//Este obligata sa implementeze ftest()
class A implements IConst
{
A()
{
System.out.println("Constructor..");
};
public void ftest()
{
System.out.println("ftest() la lucru...");
};
}
public class TInterf1
{

public static void main(String s[])


{
//Creare variabila obiect
//de tip A
//se mostenesc constantele
//interfetei IConst
A va=new A();
System.out.println(va.Numar);
System.out.println(va.s);
va.ftest();
//Creare variabila obiect
//de tip IConst
IConst iva=new A();
System.out.println(iva.Numar);
System.out.println(iva.s);
iva.ftest();
};
}
nainte de a pune punct subiectului s mai precizez urmtoarele:

Un program nu poate crea instane dintr-o interfat.


Toate metodele unei interfee sunt implicit publice i abstracte. Nici un alt tip nu este permis.
Toate metodele trebuie s fie implementate de clasa care utilizeaz interfaa.

5 Polimorfismul n programarea orientat pe obiecte


din perspectiv Java
5.1 S reamintim, pe scurt, ce este polimorfismul.
Dup cum stau lucrurile n limbajele de programare orientate pe obiecte, polimorfismul este singurul
principiu a crui for se manifest n timpul execuiei programelor. Valoarea principiului motenirii este esenial
concentrat n posibilitatea de a reutiliza efortul de dezvoltare a unui sistem soft. ncapsularea este, de asemenea,
un principiu a crui manifestare nu este evident dect de pe poziia de programator, n esen. Ar fi, ns,
nedrept s nu subliniem c att ncapsularea ct i motenirea trebuie s fie mnuite cu mult abilitate
pentru a obine efecte polimorfice de mare subtilitate i utilitate.
ncercnd o definiie a polimorfismului, independent de limbajul de programare i din punctul de
vedere al programatorului care beneficiaz de el, numim polimorfism posibilitatea ca un apel de funcie
(metod , operaie) s genereze rspunsuri diferite n funcie de contextul n care a fost formulat.

5.2 Tipuri de polimorfism la nivelul limbajelor de programare.


Exemplificare recapitulativ n C++.
Nevoia de polimorfism, resimit acut mai ales n programare, este n mare msur sinonim cu nevoia
de confort. n stadiul n care se afl, actualmente, realizrile specialitilor n materie de polimorfism la nivelul
limbajelor de programare, putem semnala urmtoarele tipuri importante de polimorfism:

Polimorfismul orientat pe suprascrierea funciilor n programarea clasic.


Polimorfismul orientat pe suprascrierea funciilor n cadrul definiie i unei clase.
Polimorfsimul orientat pe suprancrcarea operatorilor n programarea orientat pe obiecte.
Polimorfismul orientat pe redefinirea funciilor n programarea orientat pe obiecte, ntr-un lan
de derivare.

Indiferent de tipul lui, polimorfismul de calitate cere investiie de timp i creativitate, pe moment, n
beneficiul unor viitoare reutilizri, cu minimum de efort din partea clienilor.
Polimorfismul orientat pe suprascrierea funciilor n programarea clasic
Aceast form de polimorfism este, practic, cea mai veche. Ea presupune posibilitatea de a scrie funcii care
au acelai nume, retuneaz acelai tip de dat, dar se pot deosebi prin tipul i numrul parametrilor. Aceast
posibilitate este ilustrat n Exemplul 5.1, perfect legal n programarea n limbajele C/C++.
Exemplul 5.1
//Suprascrierea funciilor n programarea clasic n C
//Sunt specificate i implementate dou versiuni,
//diferite prin lista de parametri ale funciei suma()
#include <iostream.h>
#include <conio.h>
//Prima versiune a funciei suma()
//Parametrul s este transmis prin referin
void suma(float &s,int o1,int o2)
{
s=o1+o2;
};

//A doua versiune a funciei suma()


//Parametrul s este transmis prin re ferin
void suma(float &s,int o1, int o2, int o3)
{
s=o1+o2+o3;
};

void main()
{
float st;
clrscr();
//Utilizarea versiunii 2
suma(st,12,13,14);
cout<<st<<endl;
//Utilizarea versiunii 1
suma(st,12,13);
cout<<st;
getch();
};
Care sunt observaiile care se impun? Mai nti, este de remarcat faptul c trebuie s existe un programator
care este suficient de informat cu privire la variaiile de comportament ale unei funcii avnd acelai nume i care
returneaz acelai tip de dat. Dei nu excludem posibilitatea de a ntlni o astfel de situaie i n alte contexte,
programatorii versai tiu foarte bine ct de mult valoreaz versionarea unei funcii n programarea generic,
atunci cnd soluia template-urilor prezint unele inconveniente. n al doilea rnd, dac versionarea este realizat
cu sim de rspundere, utilizarea diferitelor versiuni n diferite situaii este extrem de comod i benefic, gsind
o soluie de partajare a codului versiunilor ntre mai multe programe. n al treilea rnd, nu putem trece cu
vederea faptul c la compilare este realizat legarea unui apel de versiune de codul aferent (acest gen de legare se
numete early binding).
Polimorfismul orientat pe suprascrierea funciilor n cadrul definiie i unei clase
Aceast form de polimorfism satisface unele cerine de versionare a comportamentului operaiilor unei
clase, n spiritul celor spuse relativ la suprascrierea n stil clasic a funciilor. Dup cum se anticipeaz n
Exemplul 5.2 (de cod C++), acest tip de polimorfism poate fi combinat cu polimorfismul orientat pe
supradefinirea metodelor ntr-un lan de derivare.
Exemplul 5.2
#include <iostream.h>
#include <conio.h>
//Clasa de baza
class Super
{
int numar;
public:
Super(int n)
{
numar=n;
};
//Versiunea 1 a functiei f1()
void f1()
{
cout<<"Super::Functie de test"<<endl;
getch();
};
//Versiunea 2 a functiei f1()
// Suprascrie prima versiune a lui f1() inauntrul
//clasei Super
//In raport cu clasa Baza f1()este virtuala
//Deci urmeaza sa fie supradefinita
virtual void f1(int n)
{
cout<<"Super::Numar: "<<n<<endl;

getch();
};
};
//Clasa derivata
class Baza:public Super
{
public:
Baza(int n):Super(n)
{
};
void f1(int n)
{
cout<<"Baza::Numar: "<<n<<endl;
getch();
};
};
void main()
{
//Pointer la Super
Super *PSuper;
//Alocare dinamic a memoriei pentru pointer -ul Psuper
//n context Super
PSuper=new Super(10);
clrscr();
//Utilizare Psuper; apelare succesiva a doua versiuni ale
//functiei f1()
PSuper->f1();
PSuper->f1(10);
delete PSuper;
//Alocare dinamic a memoriei pentru pointer -ul PSuper
//n context Baza
PSuper=new Baza(12);
PSuper->f1(12);
delete Psuper;
};
Polimorfsimul orientat pe suprancrcarea operatorilor n programarea orientat pe obiecte
Subiect ocolit de specificatorii limbajului Java, ns generator de satisfacii deosebite pentru
programatorii n C++. Ideea de baz const n faptul c este la latitudinea celor care programeaz orientat pe
obiecte n C++ s redefineasc comportamentul unui foarte mare numr de operatori (+, -, *, >>, <<, new,
delete, etc.).
Atenie! Nu poate fi schimbat nici aritatea nici prioritatea operatorilor predefinii, prin
suprancrcare.
Protocolul de suprancrcare a unui operator, astfel nct acesta s opereze asupra obiectelor unei clase
este urmtorul:
1.

Definiia clasei trebuie s conin o funcie operator membru sau o funcie operator prieten,
avnd sintaxa special:
Varianta funcie membr
<Tip returnat> operator # (<Lista de argumente>);
sau

Varianta funcie friend


friend <Tip returnat> operator # (<Lista de argumente>);
n aceast sintax, atrag atenia cuvntul cheie operator (care informeaz compilatorul c funcia
suprancarc un operator) i caracterul # care semnific un substitut pentru operatorul pe care dorii s-l
suprancrcai, altul dect: . , * , :: , ? .
De remarcat faptul c, alegnd varianta funcie membr, un operator binar va fi specificat ca o funcie
cu un parametru, care va indica operandul din stnga, operandul din dreapta fiind vizibil prin
intermediul pointerului this. De asemenea, dac alegem varianta funcie membr, un operator unar va
fi implementat ca o funcie fr parametri, pointerul this permind referirea operandului. Defeciunea
n cazul utilizrii unei funcii membru pentru suprancrcarea unui operator este clar: parametrul din
stnga trebuie s fie un obiect, nu poate fi o constant. Este evident c, n aceste condiii funciile
prietene sunt de preferat.
2.

Funciile operator se vor implementa folosind una din sintaxele:

<Tip returnat> <Nume clas>::operator # (<Lista de argumente>)


{
// Corp funcie operator specificat ca membr
};
sau
<Tip returnat> operator # (<Lista de argumente>)
{
// Corp funcie operator specificat ca prieten
};
Lucrurile pot fi nelese i mai bine, urmrind Exemplul 5.3 (cod C++).
Exemplul 5.3
#include<conio.h>
#include<iostream.h>
//Clasa complex contine functia operator + ca membru
//operatorul + este extins la multimea numerelor complexe
//cu ajutorul unei metode membru a clasei complex
//Clasa complex contine functia operator - ca functie friend
//operatorul - este extins la multime numerelor complexe
//cu ajutorul unei metode friend
class complex
{
float x,y;
public:
complex(){};
complex(float a,float b)
{
static int i;
i++;
clrscr();
cout<<"Lucreaza constructorul...Obiectul->:"<<i;
getch();
x=a;
y=b;
};
void disp_nc();
//prototipul operatorului +

complex operator+(complex &op2);


//prototipul operatorului friend complex operator-(complex &op1,complex &op2);
};
void complex::disp_nc()
{
cout<<x<<"+i*"<<y;
};
//Implementare operator +
//Aceasta sintaxa transforma apelul <ob1+ob2>
//in +(ob2), ob1 fiind accesibil prin pointerul
//special <this>
complex complex::operator+(complex &op2)
{
complex temp;
temp.x=op2.x+x;
temp.y=op2.y+y;
return temp;
};
complex operator -(complex &op1,complex &op2)
{
complex temp;
temp.x=op1.x-op2.x;
temp.y=op1.y-op2.y;
return temp;
};
void main()
{
complex tamp1,tamp2;
complex *pod1,*pod2;
complex ob1(10,10),ob2(11,11);
clrscr();
gotoxy(20,10);cout<<"Primul numar complex ->:";
ob1.disp_nc();
getch();
gotoxy(20,11);cout<<"Al doilea numar complex->:";
ob2.disp_nc();
getch();
ob1=ob1+ob2;
gotoxy(20,13);cout<<"Suma numerelor complexe->:";
ob1.disp_nc();
getch();
pod1=new complex(200,200);
pod2=new complex(300,300);
tamp1=*pod1;
clrscr();
gotoxy(20,10);cout<<"Al treilea numar complex
tamp1.disp_nc();

->:";

tamp2=*pod2;
gotoxy(20,11);cout<<"Al patrulea numar complex ->:";
tamp2.disp_nc();

gotoxy(20,14);cout<<"Suma numerelor complexe->:";


tamp1=tamp1+tamp2;
tamp1.disp_nc();
tamp1=*pod1;
tamp2=*pod2;
tamp1=tamp1-tamp2;
gotoxy(20,15);cout<<"Diferenta numerelor complexe->:";
tamp1.disp_nc();
getch();
}
Polimorfismul orientat pe redefinirea funciilor n programarea orientat pe obiecte, ntr-un lan de
derivare
Este element suport esenial pentru specializarea claselor ntr-un lan de derivare, specializare care se
realizeaz prin redefinirea comportamentului unor metode ale strmoilor. Pentru a se mbina extinderea
comportamentului cu reutilizarea codului, este de dorit ca redefinirea comportamentului s planifice utilizarea
comportamentului versiunii din strmo.
Exemplul 5.4 ne arat cum se pune problema redefinirii n C++.
Exemplul 5.4
#include <iostream.h>
#include <conio.h>
//Structura suport pentru pastrarea
//coordonatelor varfurilor poligoanelor
struct Varf
{
int x,y;
Varf *Legs;
};
//Clasa Poligon
//Clas abstracta->nu are constructor i destructor
//Furnizeaz prototipurile metodelor definitie() i arie()
//ca metode virtuale pure.
//Furnizeaz implementarea pentru metodele:
//
perimetru()
//
ElibMem()
//
setare_pvarfuri()
//
consultare_pvarfuri()
//
setare_nrvarfuri()
//
consulatre_nrvarfuri()
class Poligon
{
Varf *pvarfuri;
int nrvarfuri;
public:
//Metode virtuale pure
//Vor fi redefinite n descendeni
virtual void definitie()=0;
virtual float arie()=0;
float perimetru();
void ElibMem();
void setare_pvarfuri(Varf *p);
Varf * consultare_pvarfuri();
void setare_nrvarfuri(int nv)
{
nrvarfuri=nv;

};
int consultare_nrvarfuri()
{
return nrvarfuri;
};
};
float Poligon::perimetru()
{
cout<<"perimetru(): ";
cout<<"Calculul perim. este neimplem... Poligon" <<endl;
getch();
return 0;
};
void Poligon::ElibMem()
{
Varf*pwork;
while (pvarfuri!=NULL)
{
pwork=pvarfuri->Legs;
delete pvarfuri;
pvarfuri=pwork;
};
};
void Poligon::setare_pvarfuri(Varf *p)
{
pvarfuri=p;
};
Varf * Poligon::consultare_pvarfuri()
{
return consultare_pvarfuri();
};
//Clasa Triunghi
//Clas concret avnd ca superclas clasa Poligon
//Redefinete comportamentul metodelor:
//
definitie(); arie()
//Furnizeaz constructor i destructor
class Triunghi:public Poligon
{
public:
Triunghi(Varf *pt,int tnrv)
{
setare_pvarfuri(pt);
setare_nrvarfuri(tnrv);
cout<<"Constructor Tringhi..."<<endl;
};
virtual ~Triunghi()
{
cout<<"Destructor Triunghi..."<<endl;;
ElibMem();
};
//Redefinire metode
void definitie();

float arie();
};
void Triunghi::definitie()
{
cout<<"definitie(): ";
cout<<"Triunghiul este poligonul cu trei laturi"<<endl;
getch();
};
float Triunghi::arie()
{
cout<<"arie(): ";
cout<<"Neimplementata deocamdata...Triunghi"<<endl;
getch();
return 0;
};
class Patrulater:public Poligon
{
public:
Patrulater(Varf *pt,int tnrv)
{
setare_pvarfuri(pt);
setare_nrvarfuri(tnrv);
cout<<"Constructor Patrulater..."<<endl;
};
//Destructor virtual
virtual ~Patrulater();
void definitie();
float arie();
};
Patrulater::~Patrulater()
{
ElibMem();
cout<<"Destructor Patrulater..."<<endl;
};
void Patrulater::definitie()
{
cout<<"definitie(): ";
cout<<"Patrulaterul este poligonul cu patru laturi"<<endl;
getch();
};
float Patrulater::arie()
{
cout<<"arie(): ";
cout<<"Neimplementata deocamdata...Patrulater"<<endl;
getch();
return 0;
};
class Paralelogram:public Patrulater
{
public:
Paralelogram(Varf *pt,int tnrv):Patrulater(pt,tnrv)
{

cout<<"Constructor Paralelogram..."<<endl;
};
//Destructor virtual
virtual ~Paralelogram()
{
ElibMem();
cout<<"Destructor Paralelogram..."<<endl;
};
//Redefinire metode
void definitie();
float arie();
};
void Paralelogram::definitie()
{
cout<<"definitie(): ";
cout<<"Paralelogramul este patrulat. cu laturile paral. doua cate doua"<<endl;
getch();
};
float Paralelogram::arie()
{
cout<<"arie(): ";
cout<<"Neimplementata deocamdata...Paralelogram"<<endl;
getch();
return 0;
};
class Dreptunghi:public Paralelogram
{
public:
Dreptunghi(Varf *pt,int tnrv):Paralelogram(pt,tnrv)
{
cout<<"Constructor dreptunghi..."<<endl;
};
virtual ~Dreptunghi()
{
ElibMem();
cout<<"Destructor Dreptunghi..."<<endl;
};
void definitie();
float arie();
};
void Dreptunghi::definitie()
{
cout<<"definitie(): ";
cout<<"Dreptunghiul este paralelogramul cu un unghi drept"; cout<<endl;
getch();
};
float Dreptunghi::arie()
{
cout<<"arie(): ";
cout<<"Neimplementata deocamdata...Dreptunghi"<<endl;
return 0;
};

void main()
{
Poligon *RefPol;
Patrulater *RefPatr;
clrscr();
RefPol=new Triunghi(NULL,3);
RefPol->arie();
RefPol->definitie();
RefPol->perimetru();
cout<<endl;
delete RefPol;
RefPatr=new Patrulater(NULL,4);
RefPatr->arie();
RefPatr->definitie();
RefPatr->perimetru();
cout<<endl;
delete RefPatr;
RefPatr=new Paralelogram (NULL,4);
RefPatr->arie();
RefPatr->definitie();
RefPatr->perimetru();
delete RefPatr;
};
Pentru o mai bun nelegere a Exemplului 5.4, sunt necesare o serie de precizri n ceea ce privete
genul de polimorfism ilustrat.
Mai nti, din punct de vedere sintactic, trebuie s observm faptul c informm compilatorul de
intenia de redefinire a unei metode n aval (ntr-un lan de derivare) prin specificarea acesteia n clasa
gazd ca metod virtual sau ca metod virtual pur.
Prototipul unei metode virtuale are sintaxa:
virtual <Tip returnat> <Nume metoda>([<Lista de parametri>]);
Prototipul unei metode virtuale pure are sintaxa:
virtual <Tip returnat> <Nume metoda>([<Lista de parametri>])=0;
Clasele care conin cel puin o metod virtual pur sunt clase abstracte, deci nu pot avea instane
directe, neavnd nici constructori. n schimb, clasele abstracte pot fi folosite pentru a declara referine
ctre descendeni, ceea ce exte extrem de folositor dac dorim polimorfism.
De remarcat c redefinirea se bazeaz pe o restricie important: n procesul de redefinire se conserv
signatura (numrul de parametri, tipul lor i tipul returnat).
Odat ce o metod a fost declarat virtual sau virtual pur, compilatorul tie c aceast metod este
posibil s fie redefinit n descendeni i, de asemenea, compilatorul tie c pentru clasa care conine metode
virtuale i pentru toate clasele descendente ei, la crearea primului obiect, constructorul va crea i tabela VMT
(Virtual Methode Table), o structur partajat de toate obiectele unei clase, folosit de sistem pentru a realiza
genul de legare a unui apel de codul contextual, numit late binding. Prin urmare, atunci cnd se creaz un
obiect, al crui tip definitor este undeva ntr-un lan de derivare, dac n amonte a existat intenie de redefinire a
unor metode, sistemul va crea, numai n cazul primului obiect de tipul respectiv, o tabel care conine adresele
metodelor virtuale ale clasei. Aceste adrese vor fi utilizate n procesul de late binding.
S mai observm faptul c, fr a fi prefixai de cuvntul cheie virtual, destructorii sunt apelai pe
principiul ntotdeauna lucreaz constructorul tipului definitor al unei varia bile obiect sau al unui
pointer la un obiect, ceea ce nseamn un gen de legare static a destructorului. Dac dorim legare dinamic,
atunci destructorul este declarat ca virtual.
Efectul poate fi urmrit n Exemplul 5.4.

5.3 Polimorfismul n context Java


Java implementeaz principiul polimorfismului la scara posibilitilor proprii. n Java nu avem dect
programare orientat pe obiecte, oricare ar fi calitatea acesteia. Astfel c se ofer suport pentru polimorfism
orientat pe suprascrierea funciilor i polimorfism orientat de supradefinire. Java nu ofer sintax pentru
suprancrcarea operatorilor, deci nu este posibil polimorfismul aferent. Merit s remarcm faptul c
supradefinirea n Java este mai simpl dect n C++, din punct de vedere sintactic vorbind. Pur i sumplu, dac
compilatorul sesizez c n amontele unui lan de derivare exist o metod care este supradefinit n aval, atunci
compilatorul genereaz informaii necesare pentru realizarea legrii la execuie. Cerina conservrii signaturii
n procesul de supradefinire este prezent i n Java.
Un model de utilizare a polimorfismului se poate observa n Exemplul 5.5.
Exemplul 5.5
//Clasa radacina
class Poligon
{
private String definitie;
public Poligon(String d)
{
definitie=new String(d);
};
public String citesteDefinitie()
{
return definitie;
};
//Metoda va fi supradefinita in descendenti
public void arie()
{
System.out.println("Poligon...neimplementata!");
};
};
class Triunghi extends Poligon
{
public Triunghi(String d)
{
super(d);
};
//Supradefinire
public void arie()
{
System.out.println("Triunghi...neimplementata!");
};
};
class Patrulater extends Poligon
{
public Patrulater(String d)
{
super(d);
};
//Supradefinire
public void arie()
{
System.out.println("Patrulater...neimplementata!");
};
};

public class Polimorf


{
public static void main(String[] s)
{
//Referinta la radacina
Poligon PRef;
//Alocare in context Poligon
PRef=new Poligon("Linie franta inchisa");
System.out.println(PRef.citesteDefinitie());
//Sintaxe la utilizare este aceeasi in cele trei contexte
PRef.arie();
System.out.println("");
//Alocare in context Triunghi
PRef=new Triunghi("Poligonul cu trei laturi");
System.out.println(PRef.citesteDefinitie());
PRef.arie();
System.out.println("");
//Alocare in context Patrulater
PRef=new Patrulater("Poligonul cu patru laturi");
System.out.println(PRef.citesteDefinitie());
PRef.arie();
System.out.println("");
};
};
Nu am motive s reiau discuia pe marginea mecanismului de legare dinamic a metodelor supradefinite
n Java. Chiar dac compilatorul folosete alt gen de informaii, la intrare, rezultatul final, pentru programator
este acelai.
Nu consider o problem deosebit comentarea i exemplificarea suprascrierii n clasele Java.

6 Tratarea structurat a excepiilor n programarea


orientat pe obiecte
6.1 O problem, n plus, n programare: tratarea excepiilor
Programatorii adevrai trebuie s ia, obligatoriu, n calcul i posibilitatea de a crea programe robuste,
care fac fa att cerinelor specificate dar nerafinate suficient, ct i cerinelor nespecificate dar formulate de
utilizator, din diverse motive. Programele care au aceste caliti se numesc robuste.
n programarea clasic, soluia acestei probleme se putea numi, destul de exact spus, programare
defensiv. Seamn puin cu conducerea preventiv din oferie dac ne gndim c programnd defensiv, n
fond punem rul nainte, deci nu ne bazm pe cumsecdenia i buna pregtire a utilizatorului.
ncercarea de a trata situaiile de excepie care pot apare la execuia unui program, folosind metode
clasice (programarea defensiv) duce la creterea semnificativ a complexitii codului ceea ce afecteaz, n mod
direct, lizibilitatea i, n mod indirect, corectitudinea codului
Pentru a face fa cerinelor legate de problema tratrii excepiilor (aa se numesc n jargon profesional
erorile care apar n timpul execuiei programelor) anumite limbaje de programare ofer suport adecvat. Includem
aici limbaje precum: Object Pascal, C++, Java, Visual C++.
Nu toate compilatoarele de C++ ofer suport, dar standardul ANSI C++ cere acest lucru n mod explicit.
Compilatoarele din familia Borland, ncepnd cu versiunea 4.0 ofer acest suport.
Esenialul din punctul de vedere al programatorului C++ este ca el s-i formeze abilitatea de a scrie, n
jurul aplicaiilor, cod C++ care ndeplinete funcia de handler de excepii.

6.2 Maniera Java de tratare a excepiilor


Aa cum am menionat deja, ncercarea de a trata situaiile de excepie care pot apare la execuia unui
program, folosind metode clasice (programarea defensiv) duce la creterea semnificativ a complexitii
codului, ceea ce afecteaz, n mod direct, lizibilitatea i, n mod indirect, corectitudinea codului. Din aceast
cauz cei care au creat Java au gndit un sistem de tratare a excepiilor (n continu evoluie, de la o versiune la
alta a limbajului Java) care s permit programatorului:

Tratarea situaiilor de excepie, pe ct posibil, independent de fluxurile de control normale;


Tratarea excepiilor, la un nivel superior celui n care apar;
Propagarea excepiilor la nivelele superioare n mod ierarhic;
Tratarea unitar a excepiilor de acelai tip.

n mare parte, asemntor sistemului C++ de tratare a excepiilor, sistemul Java are, totui, o ofert mai bine
pus la punct din acest punct de vedere. Java se bazeaz pe un numr restrns de cuvinte cheie (try, catch,
throw, finally, throws) i pe o ierarhie de clase, specializate n tratrarea unor clase de erori.
Pentru a nelege mai bine mecanismul tratrii excepiilor n Java, consider c este util o scurt descriere a
modului n care apar i sunt procesate excepiile n Java. Astfel, cnd apare o excepie n interiorul unei metode a
unei clase Java, se creeaz un obiect excepie (obiect ce caracterizeaz excepia i starea programului n
momentul cnd excepia apare). Odat creat acest obiect, el este aruncat utiliznd cuvntul cheie throw.
Sarcina crerii i aruncrii obiectului excepie aparine programatorului. Din momentul aruncrii unui obiect
excepie, folosind cuvntul cheie throw, maina virtual Java (JVM), prin componenta RuntimeSystem, preia
obiectul i l transmite secvenei de cod responsabil de tratarea excepiei respective. n acest scop,
RuntimeSystem va cuta un handler al excepiei (=o secven de cod responsabil de tratarea excepiei),
ncepnd de la nivelul (nivelul este o metod) n care a aprut excepia i continund la nivelele superioare.
Cutarea se face n urm (backward), utiliznd stiva de apel (call stack). Primul handler (un bloc try-catch),
corespunztor obiectului excepie, se va ocupa de soluionarea excepiei. Dac RuntimeSystem a epuizat stiva
de apel, fr a gsi o metod care s ofere un handler al obiectului excepie aruncat, RuntimeSystem va fi
responsabil de tratarea excepiei respective (va afia un mesaj de eroare i va opri firul de execuie). Mecanismul
descris mai sus poate fi vizualizat ca n Figura 19.
Problema care se afl n faa programatorului este, evident, urmtoarea: cum poate folosi raional
mecanismul respectiv? Spun aceasta deoarece, ca orice facilitate a limbajului i suportul oferit pentru tratarea
excepiilor poate fi utilizat n mod abuziv. A abuza de tratarea excepiilor nseamn a vedea excepii i unde nu
este cazul, fapt care provoac complexificarea artificial a codului i, foarte important, diminueaz

performanele programului, deoarece, a cum rezult i din Figura 17, mecanismul tratrii excepiilor consum
resurse pentru a se desfura corespunztor. De aceea, este necesar
o disciplinare a gndirii
programatorului, n ceea ce privete decizia de a considera excepie sau nu un anumit context de
prelucrare, n interiorul unei metode i apoi, decizia de a aborda, ntr-un anumit mod, problema tratrii
excepiei respective. n esen, programatorul trebuie s acumuleze suficien experien nct s deosebeasc
o excepie nerecuperabil de o excepie din care se poate reveni.
RuntimeSuystem - JVM
-preia obiectul excepie
-caut, ncepnd cu nivelul j, n
sus, primul handler
corespunztor (=primul handler
care rezolv o excepie de tipul
celei aruncate)
-transfer obiectul excepie
handler-ului

Nivel_1

Nivel_i Nivel Tratare


Excepie
Conine un handler (un bloc
try-catch)
-preia obiect excepie
-trateaz excepie

Nivel_j Nivel apariie


excepie
-creaz obiectul excepie
Exception exc=new
Exception();
-arunc excepia
throw(exc);

Figura 16. Mecanismul Java de tratare a excepiilor


Pentru a crea un obiect excepie, Java pune la dispoziia utilizatorului o ierahie de clase, aflat n
pachetul java.lang. Pe lng clasele de tip excepie aflate n java.lang, fiecare pachet Java introduce propriile
tipuri de excepii. Utilizatorul nsui poate defini clase de tip excepie, care ns pentru a avea instane
compatibile cu sistemul Java, trebuie s fie descendeni ai clasei Throwable, clas care ocup o poziie
important n ierarhia simplificat a claselor de tip excepie, prezentat n Figura 18.

Throwable

Exception

Error

RuntimeException

Figura 17. Ierarhia simplificat a claselor de tip excepie din pachetul java.lang
Dup cum se poate observa n Figura 18, clasa Throwable are doi descendeni: clasa Error i clasa
Exception. Nici una din cele dou clase nu adaug metode suplimentare, dar au fost introduse pentru a delimita
dou tipuri fundamentale de excepii care pot apare ntr-o aplicaie Java (de fapt, acest mod de gndire este
aplicabil n orice limbaj de programare care ofer suport pentru tratarea sistematic a excepiilor).
Clasa Error corespunde excepiilor care nu mai pot fi recuperate de ctre programator. Apariia unei
excepii de tip Error impune terminarea programului. Aruncarea unei excepii de tip Error nseamn c a aprut
o eroare deosebit de grav n execuia programului sau n maina virtual Java. n marea majoritate a cazurilor,

aceste excepii nu trebuie folosite de ctre programator, nu trebuie prinse prin catch, i nici aruncate prin throw
de ctre programator. Aceste tipuri de erori sunt utilizate de JVM, n vederea afirii mesajelor de eroare.
Clasa Exception este, de fapt, clasa utilizat efectiv de ctre programatori n procesul de tratare a
excepiilor. Aceast clas i descendenii ei modeleaz excepii care pot fi rezolvate de ctre program, fr a
determina oprirea programului. Prin urmare, regula este simpl: dac Java nu conine o clas derivat din
Exception care poate fi utilizat ntr-un anumit context, atunci programatorul va trebui s o
implementeze, el nsui, ca o clas derivat din Exception.
Exist o mare varietate de clase derivate din Exception care pot fi utilizate. Mai mult, fiecare pachet
Java adaug noi tipuri de clase derivate din Exception, clase legate de funcionalitatea pachetului respectiv.
Dac astfel lucreaz cei de la SUN, de ce n-ar lucra la fel i un programator oarecare?
Din categoria claselor derivate din Exception, se remarc clasa RuntimeException 13 i clasele derivate
din ea. Din aceast categorie fac parte excepii care pot apare n execuia unui program, n urma unor operaii
nepermise de genul: operaii aritmetice interzise (mprire la zero), acces nepermis la un obiect (referin null),
depirea index-ului unui tablou sau ir, etc.
Nu ne rmne dect s prezentm protocolul de lucru cu excepii n Java.
Aruncarea excepiilor
Aruncarea unei excepii se face cu ajutorul cuvntului cheie throw, conform sintaxei:

throw <obiectExceptie>;

unde <obiectExceptie> este o instana a clasei Throwable sau a unei clase, derivat din aceasta. Evident, n
locul variabilei <obiectExceptie> poate fi o expresie care returneaz un obiect de tip convenabil. De fapt, n
practic, modul de aruncare a unei excepii urmeaz schema:

throw new <clasaExceptie>(Mesaj);

Evident, putem avea i cazuri n care o funcie poate arunca n mod indirect o excepie, ceea ce
nseamn c funcia nu va conine o expresie throw, ci va apela o funcie care poate arunca o excepie.
O metod poate arunca mai multe excepii. Important este s nelegem c prin aruncarea unei excepii
se iese din metod fr a mai executa secventele de cod care urmau. n cazul n care o funcie arunc o excepie,
fie prin throw , fie prin apelul unei funcii, fr a avea o secven try-catch de prindere atunci aceast funcie
trebuie s specifice clar aceast intenie n definiia funciei. Pentru acest caz, sintaxa de definire a funcie este:
public void <numeMetoda> throws <clasExcept1>,<clasExcept2>,
{

throw <obiectExcep1>;

throw <obiectExcept2>;

};

Prinderea excepiilor
Pentru a beneficia de avantajele mecanismului de tratare a excepiilor, odat ce am aruncat o excepie
este nevoie s o prindem. Prinderea unei excepii se face prin intermediul unui bloc try-catch, a crui sintax
generic este prezentat mai jos.

try
13

Detalii cu privire la descendenii clasei RuntimeException se pot gsi n Clin Marin Vduva, Programarea
n Java, Editura Albastr, 2001.

{
//Cod ce poate arunca o excepie
}
catch(<clasExcept1> <idExcept1>)
{
//handler exceptie de tip <clasExcept1>
}
catch(<clasExcept2> <idExcept2>)
{
//handler exceptie de tip <clasExcept2>
}

[finally
{
//secvena de cod executat oricum
}]

Dup cum se poate observa, structura de prindere a excepiilor poate fi delimitat n trei blocuri.
Blocul try, numit i bloc de gard atrage atenia c secvena de cod inclus n el poate arunca, n
anumite condiii, excepii. n cazul n care acest lucru nu se ntmpl, secvena din interiorul blocului de gard se
execut n ntregime, controlul fiind predat primei instruciuni de dup construcia try-catch.
n cazul n care se arunc o excepie, execuia secvenei din blocul de gard se ntrerupe i se
declaneaz procedura de tratare a excepiei.
Tratarea excepiei se poate face prin intermeiul blocurilor catch, numite i handlere de excepii. n
momentul n care apare o excepie n regiunea de gard, se parcurge lista blocurilor catch n ordinea n care apar
n programul surs. n cazul n care excepia aruncat corespunde unui bloc catch, se execut codul eferent
blocului i se termin cutarea n list, considerndu-se c excepia a fost rezolvat. Sintaxa ne arat c pot exista
mai multe blocuri catch, ceea ce nseamn c n blocul de gard pot fi aruncate excepii de mai multe tipuri.
Situaiile deosebite care pot apare n utilizarea blocurilor catch sunt urmtoarele: am putea dori s
tratm excepii de tip EC1 i EC2, unde EC2 este o clas derivat din EC1. Datorit faptului c blocurile
catch sunt parcurse secvenial este necesar s avem handler-ul clasei EC2 naintea handler-ului clasei EC1,
altfel, nu se va ajunge niciodat la secvena catch de tratare a excepiilor de tipul EC2.
De asemenea, putem avea situaii n care s dorim tratarea unei excepii pe mai multe nivele. n acest
caz, se poate lua n considerare faptul c, odat prins o excepie ntr-un bloc catch, o putem re-arunca cu un
apel simplu de tip throw.
n sfrit, blocul finally, dac este folosit, cuprinde secvena de cod care se va executa, indiferent dac
apare sau nu o excepie, situaie reclamat de nenumrate contexte n care apariia unei excepii, ca i lipsa
acesteia, presupun rezolvarea unor probleme care pot scuti sistemul de introducerea unor elemente perturbatoare
prin nerezolvarea lor.
n Exemplul 6.1 i n Exemplul 6.2 se pot vedea elementele de baz ale tratrii excepiilor ntr-o
aplicaie Java. Utilizarea cuvntului cheie finally nu mi se pare o problem deosebit.
Exemplul 6.1
//Metoda arunca o exceptie la nivelul superior
//Clasa care modeleaza exceptiile clasei NumarReal
class ENumarReal extends Exception
{
public ENumarReal(String s)
{
super(s);
};
}
//Clasa NumarReal
//o tentativa de modelare a lucrului cu numere reale
class NumarReal
{
private double numar;

public NumarReal(double nr)


{
numar=nr;
};
public double getNumar()
{
return numar;
};
//Metoda div() imparte doua numere reale
//Suspecta de a arunca o exceptie la impartirea la zero
//Declara acest lucru cu ajutorul cuvantului cheie throws
public NumarReal div(NumarReal n) throws ENumarReal
{
if (n.getNumar()==0)
throw new ENumarReal("Exceptie...Impartire la zero...");
else
return new NumarReal(this.getNumar()/n.getNumar());
};
}
public class Except1
{
public static void main(String [] s)
{
//Blocul de garda care capteaza exceptia aruncata
//de metoda div()
try
{
NumarReal onr1=new NumarReal(12);
NumarReal onr2=new NumarReal(6);
System.out.println(onr1.div(onr2).getNumar());
onr1=new NumarReal(11);
onr2=new NumarReal(0);
onr1.div(onr2);
}
catch(ENumarReal e)
{
System.out.println(e.getMessage());
};
};
};
Exemplul 6.2
//Metoda arunca o exceptie dar o si capteaza
//Clasa care modeleaza exceptiile clasei NumarReal
class ENumarReal extends Exception
{
public ENumarReal(String s)
{
super(s);
};
}
//Clasa NumarReal
//o tentativa de modelare a lucrului cu numere reale
class NumarReal
{

private double numar;


public NumarReal(double nr)
{
numar=nr;
};
public double getNumar()
{
return numar;
};
//Metoda div() imparte doua numere reale
//suspecta de a genera o exceptie la impartirea la zero
//Are bloc try-catch pentru captarea si tratarea
//exceptiei
public NumarReal div(NumarReal n)
{
try
{
if (n.getNumar()==0)
throw new ENumarReal("Exceptie...Impartire la zero...");
else
return new NumarReal(this.getNumar()/n.getNumar());
}
catch(ENumarReal e)
{
System.out.println(e.getMessage());
return new NumarReal(0);
};
};
}
public class Except
{
public static void main(String [] s)
{
NumarReal onr1=new NumarReal(12);
NumarReal onr2=new NumarReal(6);
System.out.println(onr1.div(onr2).getNumar());
onr1=new NumarReal(11);
onr2=new NumarReal(0);
onr1.div(onr2);
};
};

7 Programare generic n C++ i Java


7.1 Ce este programarea generic
Adeseori, programatorul se afl n situaia de a efectua acelai tip de prelucrare asupra unor tipuri de
date diferite. Soluia nceptorului este scrierea de cod complet pentru fiecare tip de dat. Vrem s sortm un
fiier dup o cheie ntreag? Scriem o funcie care realizeaz acest lucru, folosind, de exemplu, metoda bulelor.
Vrem s sortm un fiier dup o cheie alfanumeric? Scriem o funcie care tie s sorteze fiierul dup o astfel de
cheie, folosind tot metoda bulelor. Nu ne va fi greu s observm c, n cele dou rezolvri date de noi exist
un element de invarian: codul ablon care efectueaz sortarea. Deosebirile se refer la tipurile de date
implicate n procesul de sortare (fiierele pot avea nregistrri de lungime diferit i, evident, cu structur
diferit iar cheile de sortare pot fi diferite ca tip). Problema n faa creia ne aflm nu este o problem de
algoritmic ci una de tehnic de programare. Programarea care are n vedere specificarea unor structuri de
prelucrare capabile s opereze asupra unor tipuri variate de date se numete programare generic.
Evident, exist limbaje de programare n specificarea crora au fost prevzute i elemente suport pentru
rezolvarea acestui tip de problem. De exemplu, n Object Pascal se poate face programare generic apelnd la
tipuri procedurale i la referinele de tip pointer. n C++ se pot utiliza, n scopuri generice, suprascrierea
funciilor, conceptul de pointer, funciile ablon sau clasele ablon i pointerii la funcii. n sfrit, n Java,
utiliznd cu abilitate motenirea i interfeele putem simula genericitatea de o manier destul de acceptabil.
A evidenia, dintre toate tipurile de elemente suport prezentate mai sus, clasele ablon din C++, socotite
abstracii foarte puternice, care permit simularea a ceea ce, n ingineria softului, numim metaclase.

7.2 Genericitatea n Java


Java nu dispune de pointeri i de template-uri n adevratul sens al cuvntului. S-ar putea crede c
genericitatea este dificil sau aproape imposibil n Java. Adevrul este c lucrurile nu stau chiar aa. n
programarea orientat pe obiecte Java, putem combina fora referinelor la clase cu puterea oferit de motenire
i interfee pentru a obine un suport interesant pentru programarea generic. Motenirea ajut la crearea
cadrului organizat n care putem specifica mai multe tipuri de obiecte asupra crora efectum aceleai
prelucrri. Conversiile down, permise ntre rubedeniile unei ierarhii de clase sunt eseniale pentru a
implementa genericitatea. Interfeele ajut la specificarea cadrului natural de introducere, n Java, a referintelor
la metodele membre ale unor clase. Exemplul 7.1 ilustreaz rolul motenirii n scrierea de cod Java pentru
crearea i vizualizarea unei liste simplu nlnuite generice.
Exemplul 7.2 ilustreaz simularea pointerului la o metod generic, n Java, cu ajutorul unei instane a
unei clase singleton.
Exemplul 7.3 ilustreaz simularea pointerului la o metod generic, n Java, cu ajutorul interfeelor.
Exemplul7.1
//Clasa care modeleaza nodul listei
//capabil sa pastreze orice tip de data
class Nod
{
private Object inf;
Nod legs;
public Object read()
{
return inf;
};
public void write(Object x)
{
inf=x;
};
}
//Clasa care modeleaza comportamentul
//unei liste simplu inlantuite
class Lista
{

Nod start;
Nod prec;
public Lista()
{
start=null;
};
public void adaugdupa(Object on)
{
if(start==null)
{
Nod tamp=new Nod();
start=tamp;
start.legs=null;
start.write(on);
prec=start;
}
else
{
Nod tamp=new Nod();
tamp.write(on);
prec.legs=tamp;
tamp.legs=null;
prec=tamp;
}
}
//Metoda nu respecta cerintele
//care i-ar da dreptul sa figureze
//in API-ul clasei.
//Am specificat-o din motive didactice.
//Se poate observa un prilej potrivit pentru utilizarea
//enuntului instance of
//In intentie, aceasta metoda este un iterator
public void PentruToate()
{
Nod w=start;
int tip=0;
Integer i;
String s;
do
{
if(w.read() instanceof Integer) tip=1;
if(w.read() instanceof String) tip=2;
switch(tip)
{
case 1:
{
i=(Integer)(w.read());
System.out.println(i);break;
}
case 2:
{
s=(String)(w.read());
System.out.println(s);break;
}
};
w=w.legs;
}
while(w!=null);

}
}
public class CreLisGen
{
public static void main(String[] arg)
{
Nod obiect;
Lista lis=new Lista();
for(int i=0;i<8;i++)
{
obiect=new Nod();
obiect.write(new Integer(i).toString());
lis.adaugdupa(obiect.read());
obiect=new Nod();
obiect.write(new Integer(i));
lis.adaugdupa(obiect.read());
}
lis.PentruToate();
}
}
Exemplul 7.2
//Clasa pretextInt introduce o strategie concreta de comparare
//relativ la numere intregi
//Exemplu de clasa SINGLETON
class pretextInt
{
//Constructor privat
//pentru a asigura caracterul de singleton
private pretextInt()
{
};
public static final pretextInt INSTANCE=new pretextInt();
public int comp(Object a,Object b)
{
Integer ia,ib;
ia=(Integer)a;
ib=(Integer)b;
if(ia.intValue()<ib.intValue())return -1;
if(ia.intValue()==ib.intValue())return 0;
else return 1;
};
};
//Clasa pretextInt introduce o strategie concreta de comparare
//relativ la numere reale in virgula mobila
//Exemplu de clasa SINGLETON
class pretextFlo
{
//Constructor privat
//pentru a asigura caracterul de singleton
private pretextFlo()
{
};

public static final pretextFlo INSTANCE=new pretextFlo();


public int comp(Object a,Object b)
{
Float fa,fb;
fa=(Float)a;
fb=(Float)b;
if(fa.floatValue()<fb.floatValue())return -1;
if(fa.floatValue()==fb.floatValue())return 0;
else return 1;
};
};
public class Simpfunc
{
public static void main(String[] s)
{
Integer nri1=new Integer(100);
Integer nri2=new Integer(200);
Float nrf1=new Float(1.75);
Float nrf2=new Float(1.0);
System.out.println(pretextInt.INSTANCE.comp(nri1,nri2));
System.out.println(pretextFlo.INSTANCE.comp(nrf1,nrf2));
};
};
Exemplul 7.3
//Interfata prin intermediul careia se va simula
//ideea de pointer la metoda comp
interface SimPointMet
{
int comp(Object a,Object b);
};
//Clasa gazda a primei versiuni a metodei comp
//Va utiliza interfata SimPointMet
class pretextInt implements SimPointMet
{
public pretextInt()
{
};
public int comp(Object a,Object b)
{
Integer ia,ib;
ia=(Integer)a;
ib=(Integer)b;
if(ia.intValue()<ib.intValue())return -1;
if(ia.intValue()==ib.intValue())return 0;
else return 1;
};
};
//Clasa gazda a celei de-a doua versiuni a metodei comp
//Va utiliza interfata SimPointMet
class pretextFlo implements SimPointMet
{
public pretextFlo()

{
};
public int comp(Object a,Object b)
{
Float fa,fb;
fa=(Float)a;
fb=(Float)b;
if(fa.floatValue()<fb.floatValue())return -1;
if(fa.floatValue()==fb.floatValue())return 0;
else return 1;
};
};
public class PointMet
{
public static void main(String[] s)
{
//Interfata SimPointMet lucreaza in context pretextInt
Integer ni1,ni2;
Float nf1,nf2;
SimPointMet INSTANCE1=new pretextInt();
//Interfata SimPointMet lucreaza in context pretextFlo
SimPointMet INSTANCE2=new pretextFlo();
ni1=new Integer(100);
ni2=new Integer(200);
nf1=new Float(200);
nf2=new Float(100);
System.out.println(INSTANCE1.comp(ni1,ni2));
System.out.println(INSTANCE2.comp(nf1,nf2));
};
};

Bibliografie esenial
[1]
[2]
[3]
[4]
[5]
[6]

Eckel, B., Thinking in Java, 2nd edition, Revision 12, format electronic.
Jamsa & Klander, C i C++ (Manualul fundamental de programare n C
i C++), Editura Teora.
Joshua Bloch, Java. Ghid practic pentru programatori avansai , Editura
Teora, 2002.
Lemay, L., Cadenhead, R., Java 2 fr profesor n 21 de zile, Editura
Teora, 2000.
Mark C. Chan, .a., Java. 1001 secrete pentru programatori, Editura
Teora
Negrescu,L., Limbajele C i C++ pentru nceptori, Limbajul C++
(volumul II), Editura Albastr, Cluj-Napoca

CUPRINS

CUVNT NAINTE AL AUTORULUI ................................ ................................ .............................. 3

1 CUM SE EXPLIC PERMANENTA NEVOIE DE PARADIGME NOI N INGINERIA


SOFTULUI. CE NELEGEM PRIN ORIENTAREA PE OBIECTE................................ ............ 5
1.1
1.2
2
2.1
2.2
3
3.1
3.2

CUM SE EXPLIC PERMANENTA NEVOIE DE PARADIGME NOI N INGINERIA SOFTULUI? ........ 5


CE SE NELEGE PRIN ORIENTAREA PE OBIECTE? ................................ ................................ ...... 7
CONCEPTE I PRINCIPII N PROGRAMAREA ORIENTAT PE OBIECTE ................ 11
CONCEPTE N PROGRAMAREA ORIENTAT PE OBIECTE ................................ .......................... 11
PRINCIPII N PROGRAMAREA ORIENTAT PE OBIECTE ................................ ............................ 15
SPECIFICAREA I IMPLEMENTAREA UNEI CLASE DIN PERSPECTIV JAVA....... 20
N LOC DE INTRODUCERE ................................ ................................ ................................ ............ 20
ATENIE LA IMPORTANA EFORTULUI DE ABSTRACTIZARE! ................................ .................. 20

4 MOTENIREA N PROGRAMAREA ORIENTAT PE OBIECTE DIN PERSPECTIV


JAVA................................ ................................ ................................ ................................ ..................... 29
4.1
4.2
4.3

SCURT INTRODUCERE ................................ ................................ ................................ ............... 29


MOTENIREA N JAVA ................................ ................................ ................................ ................ 30
MOTENIREA MULTIPL N JAVA ................................ ................................ .............................. 34

5 POLIMORFISMUL N PROGRAMAREA ORIENTAT PE OBIECTE DIN


PERSPECTIV JAVA................................ ................................ ................................ ........................ 39
5.1
5.2

S REAMINTIM , PE SCURT, CE ESTE POLIMORFISMUL................................. ............................. 39


TIPURI DE POLIMORFISM LA NIVELUL LIMBAJELOR DE PROGRAMARE. EXEMPLIFICARE
RECAPITULATIV N C++. ................................ ................................ ................................ .................... 39
5.3 POLIMORFISMUL N CONTEXT JAVA ................................ ................................ .......................... 49
6 TRATAREA STRUCTURAT A EXCEPIILOR N PROGRAMAREA ORIENTAT PE
OBIECTE ................................ ................................ ................................ ................................ ............. 51
6.1
6.2
7
7.1
7.2

O PROBLEM, N PLUS, N PROGRAMARE: TRATAREA EXCEPIILOR ................................ ...... 51


MANIERA JAVA DE TRATARE A EXCEPIILOR ................................ ................................ ........... 51
PROGRAMARE GENERIC N C++ I JAVA ................................ ................................ ....... 57
CE ESTE PROGRAMAREA GENERIC ................................ ................................ .......................... 57
GENERICITATEA N JAVA ................................ ................................ ................................ ........... 57

BIBLIOGRAFIE ESENIAL................................ ................................ ................................ .......... 62