Programare orientată pe obiecte
De la Wikipedia, enciclopedia liberă
| Acest articol sau această secţiune are bibliografia incompletă sau inexistentă. Puteţi ajuta găsind susţinere bibliografică pentru conţinutul paginii. |
|
[[wiki]]
|
Acest articol sau această secţiune trebuie pus(ă) în formatul standard. Ştergeţi eticheta la încheierea standardizării. |
| Acest articol este scris parţial sau în întregime fără diacritice. Puteţi da chiar dumneavoastră o mână de ajutor. |
| Acest articol are nevoie de ajutorul dumneavoastră! Puteţi contribui la dezvoltarea şi îmbunătăţirea lui apăsând butonul „modifică pagina”. |
| Acest articol are nevoie de atenţia unui expert în informatică. Recrutaţi unul sau, dacă sunteţi în măsură, ajutaţi chiar dumneavoastră la îmbunătăţirea articolului! |
Programarea orientată pe obiecte (POO, uneori şi Programarea orientată obiect) este o tehnică de programare.
Cuprins |
[modifică] Clase şi Obiecte
Programarea orientată obiect este unul din cei mai importanți pași făcuți în evoluția limbajelor de programare spre o mai puternică abstractizare în implementarea programelor. Ea a apărut din necesitatea exprimării problemei într-un mod mai natural ființei umane. Astfel unitațile care alcătuiesc un program se apropie mai mult de modul nostru de a gândi decât modul de lucru al calculatorului. Până la apariția programării orientate pe obiect programele erau implementate în limbaje de programare procedurale(C, Pascal) sau în limbaje care nici măcar nu ofereau o modalitate de grupare a instrucțiunilor în unitați logice(funcții, proceduri) cum este cazul limbajului de asamblare(assembler). Altfel spus o problemă preluată din natură trebuia fragmentată în repetate rânduri astfel încât sa se identifice elementele distincte, implementabile într-un limbaj de programare. O mare problemă a programării procedurale era separarea datelor de unitațile care prelucrau datele(subrutinele), ceea ce făcea foarte dificilă extinderea şi întreținerea unui program. Astfel s-a pus problema ca aceste doua entități(date şi subrutine) să fie grupate într-un anumit mod, astfel încât subrutinele sa "știe" în permanență ce date prelucrează şi, mai mult decăt atât, ele sa formeze un modul, adică o unitate care separă implementarea de interfață, ceea ce implica posibilitatea refolosirii codului. A apărut astfel conceptul de clasa. Clasa realizează, în speță, ceea ce am văzut mai înainte: grupează datele şi unitațile de prelucrare a acestora într-un modul, unindu-le astfel într-o entitate mult mai naturală. Deși tehnica se numeşte "Programare Orientată Obiect", conceptul de bază al ei este este Clasa. Clasa, pe lângă faptul că abstractizează foarte mult analiza/sinteza problemei are proprietatea de generalitate, ea desemnând o mulțime de obiecte care împart o serie de proprietăți.
De exemplu: Clasa "floare" desemnează toate plantele care au flori, precum clasa "Fruct" desemnează toate obiectele pe care noi le identificam ca fiind fructe. Bineînţeles, în implementarea efectiva a programului nu se lucrează cu entităţi abstracte, precum clasele ci se lucrează cu obiecte, care sunt "instanţieri" ale claselor. Altfel spus, plecând de la exemplul de mai sus, dacă se construieşte un program care să lucreze cu fructe, el nu va prelucra entitatea "fruct" ci va lucra cu entităţi concrete ale clasei "fruct", adică "măr", "pară", "portocală", etc.
Apare însă următoarea problemă: "cum se trece de la o structură generală la una particulară, mai precis ce înseamnă efectiv procesul de instanţiere?". Instanţierea(trecerea de la clasă la obiect) înseamnă atribuirea unor proprietăţi specifice clasei, astfel încât aceasta să indice un obiect anume, care se diferenţiază de toate celelalte obiecte din clasă printr-o serie de atribute. Dacă vom considera ca "fruct_exotic" care desemnează clasa tuturor fructelor exotice conţine proprietatea "culoare" atunci atribuind acesteia valoarea "galben" noi vom crea o noua mulţime( clasa fructelor exotice care au culoarea galbenă ) care este o subclasă a clasei "fruct_exotic", deci realizăm astfel o particularizare. Mai mult decât atât, dacă vom adăuga noi şi noi atribute vom individualiza clasa astfel încât să ajungem la un caz concret, care este Obiectul.
[modifică] Obiectele comunică între ele
Odată identificate entităţile( în speţa clasele ) ele nu rămân izolate; ele vor fi grupate în module, pachete, programe, etc., care vor stabili legături între ele. Aceste legături reflectă relaţiile care se stabilesc între clasele/obiectele problemei pe care am preluat-o din natura. Extinzând exemplul de mai sus, vom adăuga o nouă clasă: "Raft" , care va avea următoarele proprietăţi: "număr" si "conţinut". Vom instanţia(particulariza) clasa "Raft" atribuind atributelor "număr" valoarea "1" şi "conţinut" valoarea "fructe". Aceasta înseamnă că am creat un obiect al clasei "Raft" care: "este primul din magazin şi conţine fructe". Bineînţeles că acest raft va fi în relaţie cu, clasa "Fruct" pe care am exemplificat-o mai devreme. Astfel el conţine obiecte de tip "Fruct".
Relaţia pe care am enunţat-o mai sus se mai numeşte şi relaţie de compunere, o relaţie fundamentală în POO, iar clasa "Raft" se numeşte clasă compusa(eng. Agregate), fiindcă în componenţa ei intră alte clase, în cazul nostru "Fruct", cum se vede în diagrama de mai jos:
************************ ************************
* * * *
* * 1 n * *
* RAFT <>==================> FRUCT *
* * * *
* * * *
************************ ************************
Un raft conţine mai multe fructe(n)
Să considerăm în continuare că în magazin avem şi fructe care trebuie păstrate la temperaturi joase. Pentru ele vom avea nevoie de un raft special. Acest nou raft(să-l numim raft frigorific) este în esenţa tot un raft doar că are în plus proprietatea de răcire. Acest lucru ne duce cu gândirea la faptul că putem reutiliza codul scris pentru "Raft" pentru a implementa o clasă numită "RaftFrigorific". Altfel spus, dorim ca noua noastră clasă să fie o subclasă a clasei "Raft" deoarece ea "are toate proprietăţile clasei "Raft" plus altele particulare, care o diferenţiază". Acest lucru, în mod intuitiv, este numit moştenire. Moştenirea este o relaţie statică(definită în momentul programării) care pune în legătură o clasă cu alta(sau mai multe) astfel încât clasa rezultată să "preia" toate atributele clasei/claselor pe care o/le moşteneşte. Clasa care moşteneşte atributele altei clase se numeşte "clasă derivată" iar clasa care are moştenitori se numeşte "clasă de bază". Terminologia este, şi în acest caz, intuitivă. Unul din avantajele moştenirii, care se observă direct, este acela al reutilizării codului: clasa derivată nu va mai implementa metodele clasei de baza, ci va implementa numai metodele ei specifice; mai mult clasa derivată va conţine (prin intermediul moştenirii) toate atributele(date şi subrutine sau "metode") ale clasei de bază. Astfel spus şi clasa "RaftFrigorific" va avea atributele "număr" si "conţinut".
Următoarea diagramă ilustrează moştenirea:
**************************
* *
* RAFT <|-+
* * |
************************** |
|
|
************************** |
* * |
* RAFTFRIGORIFIC ---+
* *
**************************
Clasa RaftFrigorific moşteneşte clasa Raft
Moştenirea este de asemeni o relaţie fundamentala în POO, care este recunoscuta ca fiind un principiu de baza, alături de Încapsulare, şi Polimorfism;
[modifică] Clasele se comporta diferit în funcţie de tipul lor
Am văzut mai sus ca o clasa poate moşteni o alta clasă, ceea ce înseamnă că o entitate preia toate atributele altei entităţi. Putem avea, de asemeni, mai multe clase care moştenesc o clasa. Fie clasa "A" şi clasele "B", "C" şi "D"; sa presupunem ca "B", "C", "D" moştenesc pe "A". În acest caz putem face afirmaţia: "B, C şi D sunt de tip A". Aceasta înseamnă că B, C şi D moştenesc toate caracteristicile clasei A deci pot fi identificate cu o clasa de tip A.
Făcând o analogie cu exemplul anterior, dacă A -> "Fruct", B -> "mar", C -> "nuca", D -> "pruna", afirmaţia de mai sus ar suna în felul următor: "mărul, para şi nuca sunt fructe", lucru care este în mod evident adevărat. Dar sa consideram următoarea situaţie: "Fruct" poate implementa o subrutină pe care o vom numi "mănâncă-mă!". Deoarece, prin moştenire, clasele "Mar", "Par" şi "Nuca" preiau toate atributele clasei "Fruct", deci şi subrutina "mănâncă-mă!" înseamnă că un măr se mănâncă la fel ca o pruna! Bineînţeles, dacă încercăm să muşcăm cu pofta dintr-o nuca... Asta înseamnă ca "mănâncă-mă!" trebuie sa se particularizeze pentru fiecare clasa in parte, reflectând un comportament adecvat cu proprietăţile acesteia. Acest lucru mai este numit şi polimorfism.
El este al treilea şi cel mai important principiu al POO. El asigura faptul ca fiecare clasa se comporta diferit(polimorfic) la un anumit mesaj trimis către obiect(în cazul nostru, apelul subrutinei "mănâncă-mă!"). Se observa că polimorfismul există în strânsă legătură cu moştenirea, fără de care nu ar exista. El aduce însa o nuanţa moştenirii: " Preiau din clasa de baza doar acele proprietăţi care sunt comune şi reflectă un comportament adecvat structurii mele". Altfel spus, prin polimorfism pot face o moştenire selectivă.
[modifică] Concluzii
Ideea POO este de a crea programele ca o colecţie de obiecte, unităţi individuale de cod care interacţionează unele cu altele, în loc de simple liste de instrucţiuni sau de apeluri de proceduri (vezi şi programare procedurală).
Obiectele POO sunt de obicei reprezentări ale obiectelor din viaţa reală (domeniul problemei), astfel încât programele realizate prin tehnica POO sunt mai uşor de înţeles, de depanat şi de extins decât programele procedurale. Aceasta este adevărată mai ales în cazul proiectelor software complexe şi de dimensiuni mari, care se gestionează făcând apel la ingineria programării.
[modifică] Principii de bază
| Acest articol are nevoie de ajutorul dumneavoastră! Puteţi contribui la dezvoltarea şi îmbunătăţirea lui apăsând butonul „modifică pagina”. |
- Abstractizarea – Posibilitatea ca un program să ignore unele aspecte ale informaţiei pe care o manipulează, adică posibilitatea de a se concentra asupra esenţialului. Fiecare obiect în sistem are rolul unui “actor” abstract, care poate executa acţiuni, îşi poate modifica şi comunica starea şi poate comunica cu alte obiecte din sistem fără a dezvălui cum au fost implementate acele facilitaţi. Procesele, funcţiile sau metodele pot fi de asemenea abstracte, şi atunci când sunt, sunt necesare o varietate de tehnici pentru a extinde abstractizarea:
- Încapsularea – numită şi ascunderea de informaţii: Asigură faptul că obiectele nu pot schimba starea internă a altor obiecte în mod direct (ci doar prin metode puse la dispoziţie de obiectul respectiv); doar metodele proprii ale obiectului pot accesa starea acestuia. Fiecare tip de obiect expune o interfaţă pentru celelalte obiecte care specifică modul cum acele obiecte pot interacţiona cu el.
- Polimorfismul – este abilitatea de a procesa obiectele diferit în funcţie de tipul lor sau de clasa lor. Mai exact, este abilitatea de a redefini metode pentru clasele derivate. De exemplu pentru o clasă Figura putem defini o metodă arie. Dacă Cerc, Dreptunghi, etc. vor extinde clasa Figura, acestea pot redefini metoda arie.
- Moştenirea – organizează şi facilitează polimorfismul şi încapsularea permiţând definirea şi crearea unor clase specializate plecând de la clase (generale) care sunt deja definite - acestea pot împărtăşi (şi extinde) comportamentul lor fără a fi nevoie de redefinirea aceluiaşi comportament. Aceasta se face de obicei prin gruparea obiectelor în clase şi prin definirea de clase ca extinderi ale unor clase existente.Conceptul de moştenire permite construirea unor clase noi, care păstrează caracteristicile şi comportarea, deci datele şi funcţiile membru, de la una sau mai multe clase definite anterior, numite clase de bază, fiind posibilă redefinirea sau adăugarea unor date şi funcţii noi.Se utilizează ideea: ”Anumite obiecte sunt similare, dar în acelaşi timp diferite”. O clasă moştenitoare a uneia sau mai multor clase de bază se numeşte clasă derivată. Esenţa moştenirii constă în posibilitatea refolosirii lucrurilor care funcţionează.

