Sari la conținut

Programare orientată pe obiecte

De la Wikipedia, enciclopedia liberă
(Redirecționat de la Object-oriented programming)

Programarea orientată pe obiecte (POO, uneori și Programarea orientată obiect, uneori denumită ca și în limba engleză, Object Oriented Programming (OOP)) este o paradigmă de programare, axată pe ideea încapsulării, adică grupării datelor și codului care operează asupra lor, într-o singură structură. Un alt concept important asociat programării orientate obiect este polimorfismul, care permite abstractizări ce permit o descriere conceptuală mai simplă a soluției.

Clase și obiecte

[modificare | modificare sursă]

Programarea orientată pe obiect (Programare Orientată Obiectual) 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 simplu, pentru a putea fi înțeleasă de cât mai mulți programatori. Astfel unităț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 unități logice (funcții, proceduri) cum este cazul limbajului de asamblare (asembler). Altfel spus o problemă preluată din natură trebuia fragmentată în repetate rânduri astfel încât să se identifice elementele distincte, implementabile într-un limbaj de programare. O mare problemă a programării procedurale era separarea datelor de unitățile care prelucrau datele (subrutinele), ceea ce făcea foarte dificilă extinderea și întreținerea unui program. Astfel s-a pus problema ca aceste două entități (date și subrutine) să fie grupate într-un anumit mod, astfel încât subrutinele să "știe" în permanență ce date prelucrează și, mai mult decât atât, ele să formeze un modul, adică o unitate care separă implementarea de interfață, ceea ce implică posibilitatea refolosirii codului. A apărut astfel conceptul de clasă. Clasa realizează, în speță, ceea ce am văzut mai înainte: grupează datele și unităț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ă Obiectual", conceptul de bază al ei 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 efectivă 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 ce conține proprietatea "culoare" atunci atribuind acesteia valoarea "galben" noi vom crea o nouă 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.

Obiectele pot comunica între ele

[modificare | modificare sursă]

Odată identificate entitățile (în speță 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 natură. 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 (Programare Orientată Obiectual), iar clasa "Raft" se numește clasă compusă (engl. 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ță tot un raft doar că are în plus proprietatea de răcire. Acest lucru ne duce cu gândul la faptul că putem reutiliza codul scris pentru "Raft" pentru a implementa o clasă numită "Raft Frigorific". 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 bază, 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 "Raft Frigorific" va avea atributele "număr" si "conținut".

Următoarea diagramă ilustrează moștenirea:

                                     **************************
                                     *                        *
                                     *          RAFT           <|--+
                                     *                        *    |
                                     **************************    |
                                                                   |
                                                                   |
                                     **************************    |
                                     *                        *    |
                                     *     RAFT FRIGORIFIC      ---+
                                     *                        *   
                                     **************************
                                
                               Clasa Raft Frigorific moștenește clasa Raft
  

Moștenirea este de asemeni o relație fundamentală în POO (Programare Orientată Obiectual), care este recunoscută ca fiind un principiu de bază, alături de Abstractizare, Încapsulare, și Polimorfism.

Clasele se comporta diferit în funcție de tipul lor

[modificare | modificare sursă]

Am văzut mai sus că o clasă poate moșteni o altă clasă, ceea ce înseamnă că o entitate preia toate atributele altei entități. Putem avea, de asemeni, mai multe clase care moștenesc o clasă. Fie clasa "A" și clasele "B", "C" și "D"; să 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 clasă de tip A.

Făcând o analogie cu exemplul anterior, dacă A -> "Fruct", B -> "măr", C -> "nucă", D -> "prună", 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 să considerăm următoarea situație: "Fruct" poate implementa o subrutină pe care o vom numi "mănâncă-mă!". Deoarece, prin moștenire, clasele "Măr", "Pară" și "Nucă" 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 nucă! Bineînțeles, dacă încercăm să "mușcăm" cu poftă dintr-o nucă... Asta înseamnă ca "mănâncă-mă!" trebuie sa se particularizeze pentru fiecare clasă în 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 Programării Orientate Obiectual. El asigură faptul că fiecare clasă se comportă diferit (polimorfic) la un anumit mesaj trimis către obiect (în cazul nostru, apelul subrutinei "mănâncă-mă!"). Se observă că polimorfismul există în strânsă legătură cu moștenirea, fără de care nu ar exista. El aduce însă o nuanță moștenirii: "Preiau din clasa de bază doar acele proprietăți care sunt comune și reflectă un comportament adecvat structurii mele". Altfel spus, prin polimorfism pot face o moștenire selectivă.

Principii de bază

[modificare | modificare sursă]
  • Abstractizarea – Este posibilitatea ca un program să separe 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 în acest caz 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 în mod diferit, în funcție de tipul 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) deja definite - acestea pot împărtăși (și extinde) comportamentul lor, fără a fi nevoie de a-l redefini. 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ă.

Ideea POO (Programare Orientată Obiectual) 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.

  • Schach, Stephen (2006). Object-Oriented and Classical Software Engineering, Seventh Edition. McGraw-Hill. ISBN 0-07-319126-4.
  • Abadi, Martin; Luca Cardelli (1998). A Theory of Objects. Springer-Verlag. ISBN 0-387-94775-2.
  • Abelson, Harold; Gerald Jay Sussman, (1997). Structure and Interpretation of Computer Programs. The MIT Press. ISBN 0-262-01153-0.
  • Armstrong, Deborah J. (February 2006). "The Quarks of Object-Oriented Development". Communications of the ACM 49 (2): 123–128. doi:10.1145/1113034.1113040. ISSN 0001-0782. Retrieved 2006-08-08.
  • Booch, Grady (1997). Object-Oriented Analysis and Design with Applications. Addison-Wesley. ISBN 0-8053-5340-2.
  • Eeles, Peter; Oliver Sims (1998). Building Business Objects. John Wiley & Sons. ISBN 0-471-19176-0.
  • Gamma, Erich; Richard Helm, Ralph Johnson, John Vlissides (1995). Design Patterns: Elements of Reusable Object Oriented Software. Addison-Wesley. ISBN 0-201-63361-2.
  • Harmon, Paul; William Morrissey (1996). The Object Technology Casebook - Lessons from Award-Winning Business Applications. John Wiley & Sons. ISBN 0-471-14717-6.
  • Jacobson, Ivar (1992). Object-Oriented Software Engineering: A Use Case-Driven Approach. Addison-Wesley. ISBN 0-201-54435-0.
  • Kay, Alan. The Early History of Smalltalk.
  • Meyer, Bertrand (1997). Object-Oriented Software Construction. Prentice Hall. ISBN 0-13-629155-4.
  • Rumbaugh, James; Michael Blaha, William Premerlani, Frederick Eddy, William Lorensen (1991). Object-Oriented Modeling and Design. Prentice Hall. ISBN 0-13-629841-9.
  • Taylor, David A. (1992). Object-Oriented Information Systems - Planning and Implementation. John Wiley & Sons. ISBN 0-471-54364-0.
  • Schreiner, Axel-Tobias (1993). Object oriented programming with ANSI-C. Hanser. ISBN 3-446-17426-5.

Legături externe

[modificare | modificare sursă]