Sunteți pe pagina 1din 9

Lucrarea 4

Motenire i polimorfism
Cuprins
Relaia de motenire n Java .....................................................................................................................1 Reguli de vizibilitate n contextul relaiei de motenire ...........................................................................2 Constructorii i motenirea.......................................................................................................................4 Operatorul instanceof ...............................................................................................................................4 Redefinirea metodelor ..............................................................................................................................5 Legarea dinamic i constructorii.............................................................................................................7 Tem .........................................................................................................................................................8

Tehnologia orientat pe obiecte permite extinderea comportamentului unei clase existente prin definirea unei clase noi, care motenete coninutul primei clase, adugnd la acesta elementele specifice ei. Clasa motenit se numete clas de baz sau superclas, iar clasa care realizeaz extinderea se numete subclas, clas derivat, sau clas descendent. Relaia de motenire este o relaie de forma este un fel de, adic subclasa este un fel de superclas. Practic, relaia de motenire ntre clase este o reflectare a ierarhizrii existente ntre entitile modelate de clasele respective. Relaia de motenire prezint dou aspecte eseniale: reutilizare de cod; polimorfism. Relaia de motenire n Java n Java, relaia de motenire dintre o superclas i o subclas se exprim astfel: class nume_subclasa extends nume_superclasa { //coninut specific subclasei } Se consider clasa Poligon i o clas Dreptunghi care motenete clasa Poligon: class Poligon { protected double[ ] laturi; public Poligon(int n) { laturi = new double[n] } public double perimetru( ) { double s=0; for(int i=0;i<laturi.length;i++) s+=laturi[i]; return s; } } class Dreptunghi extends Poligon { public Dreptunghi(double L, double h){ super(4);
1

} public double aria( ){ return laturi[0]*laturi[1]; }

laturi[0] = laturi[2] laturi[3] = h;

L;

laturi[1]

Clasa Dreptunghi reutilizeaz codul definit n clasa Poligon, la care adaug elemente proprii. Pe lng Dreptunghi, am putea defini i alte clase, cum ar fi Triunghi, Patrat, Pentagon etc. care s moteneasc Poligon. Superclasa este factorul comun al subclaselor sale sau, altfel spus, codul factorului comun este reutilizat n subclase. Despre relaia de motenire n Java se pot spune urmtoarele: o subclas poate extinde o singur superclas (motenire simpl); o superclas poate fi motenit de mai multe subclase distincte. O subclas poate fi superclas pentru alte clase. O clas de baz mpreun cu toate descendentele ei formeaz o ierarhie de clase.

Reguli de vizibilitate n contextul relaiei de motenire


Regulile de vizibilitate vor fi discutate din dou perspective: accesul funciilor unei subclase la membrii motenii de la superclasele ei; accesul clienilor unei subclase la membrii ei, motenii sau specifici. Accesul funciilor unei subclase la membrii motenii Pentru a ilustra drepturile de acces vom lua urmtorul exemplu: class SuperClasa { private int priv; protected int prot; public int pub; } class SubClasa extends SuperClasa { private int priv_local; protected int prot_local; public int pub_local; public void metoda(SubClasa p ) { priv = 1; //eroare prot = 2; //corect pub = 3; //corect priv_local = 4; //corect prot_local = 5; //corect pub_local = 6; //corect p.priv = 1; //eroare p.prot = 2; //corect p.pub = 3; //corect p.priv_local = 4; //corect
2

} }

p.prot_local = 5; //corect p.pub_local = 6; //corect

n metodele specifice ale unei subclase pot fi referii acei membri motenii, care n superclas au fost precedai de modificatorii protected sau public. Membrii motenii, care n superclas sunt precedai de modificatorul private, dei fizic fac parte din subclas, nu sunt accesibili n metodele acesteia. Referirea membrilor motenii se face direct, folosind numele lor, la fel ca referirea membrilor specifici. Acest lucru este foarte normal, deoarece i membrii motenii sunt coninui n subclas, numai c ei nu au fost declarai explicit. Includerea lor se face automat, ca efect al clauzei extends. Acest lucru nu este valabil i pentru constructori. Revenind la exemplul cu clasele Poligon Dreptunghi, trebuie spus c un obiect al clasei Dreptunghi conine doi constructori: unul motenit, responsabil cu iniializarea poriunii motenite, i unul local, responsabil cu iniializarea poriunii specifice subclasei. Referirea n subclas la constructorul motenit se face folosind cuvntul cheie super, aa cum se observ n constructorul clasei Dreptunghi. Cuvntul super este un omolog al lui this i reprezint referina la partea motenit a unui obiect. n afar de apelul constructorului motenit, cuvntul super se va utiliza pentru a distinge ntre un membru local al subclasei i un membru motenit, ambii cu acelai nume. Accesul clienilor unei subclase la membrii acesteia Exemplului din paragraful anterior i se adaug secvena urmtoare: class Client { public void oFunctie( ) { SuperClasa sp = new SuperClasa(); SubClasa sb = new SubClasa(); sp.priv = 1; //eroare sp.prot = 2; //corect, doar dac Client i SuperClasa s-ar afla in acelai pachet sp.pub = 3; //corect sb.priv = 1; //eroare sb.prot = 2; //corect, doar dac Client i SubClasa s-ar afla n acelai pachet sb.pub = 3; //corect sb.priv_local = 4; //eroare sb.prot_local = 5; //corect, doar dac Client i SubClasa s-ar afla n acelai pachet sb.pub_local = 6; //corect

} }

n clienii unei subclase pot fi referii acei membri, motenii sau locali, care sunt precedai de modificatorul public. Membrii declarai ca protected sunt accesibili numai n situaia n care clientul se afl n acelai pachet cu subclasa

respectiv. La referirea membrilor unei subclase de ctre client, nu se face deosebire ntre membrii motenii i cei locali.

Constructorii i motenirea
n exemplul anterior se observ c cele dou clase nu au constructori explicii, constructorul SubClasa() fiind de forma: public SubClasa() { super( ); } Constructorul subclasei apeleaz constructorul no-arg al superclasei. Dac pentru SuperClasa am fi definit un constructor no-arg explicit, atunci acesta ar fi fost cel apelat de constructorul SubClasa. Dac ar fi existat un constructor oarecare n SubClasa, iar acesta nu ar fi apelat explicit vreun constructor din SuperClasa, n mod automat se ncearc apelul constructorului no-arg super(), nainte de a se executa instruciunile din constructorul SubClasa: public SubClasa(. . .) { super(); //apel implicit //alte instruciuni prevzute de programator } Dac SuperClasa nu are constructor no-arg, apelul implicit de mai sus ar genera eroare. Prin urmare, dac programatorul definete constructori explicii ntr-o subclas, el trebuie s aib grij ca aceti constructori s apeleze explicit constructorii adecvai ai superclasei: super (parametri-actuali) Un asemenea apel trebuie s fie prima instruciune din constructorul subclasei. Constructorul unei subclase se definete astfel nct lista lui de parametri s se compun dintr-un set de parametri necesari iniializrii cmpurilor motenite (transmis constructorului super) i un alt set, necesar iniializrii cmpurilor locale. Execuia constructorului se desfoar n 3 etape: apelul constructorului superclasei; iniializarea cmpurilor cu valori date la declarare i execuia blocurilor de iniializare, unde este cazul; execuia corpului propriu-zis al constructorului.

Operatorul instanceof
Prin intermediul unei referine de superclas putem indica i utiliza i obiecte ale subclaselor ei. Operatorul instanceof este util atunci cnd trebuie s cunoatem clasa concret de care aparine un obiect referit prin intermediul unei referine a unui supertip. Aplicarea operatorului se face printr-o expresie de forma: referinta_obiect instanceof nume_clasa

Redefinirea metodelor
Relaia de motenire poate fi utilizat atunci cnd o anumit clas (subclas) extinde comportamentul altei clase (superclase), n sensul c superclasa nglobeaz aspectele comune ale unei ierarhii de abstraciuni, iar subclasele adaug la aceast parte comun funciuni specifice. De asemenea, o referin la superclas poate indica i manipula obiecte ale oricrei clase descendente din ea. Manipularea se refer la faptul c, prin intermediul acelei referine se pot apela metodele definite n superclas, indiferent dac obiectul concret aparine superclasei sau uneia dintre subclase. Aceast facilitate constituie aa-numitul polimorfism parial. Folosind o referin a superclasei nu se poate, ns, apela o metod local a subclasei, dect dac se realizeaz o conversie explicit (casting) a referinei, la tipul subclasei. n Java relaia de motenire poate fi aplicat i n cazul n care se dorete ca, pe lng extinderea comportamentului, s realizm i o adaptare (specializare) a lui, n sensul c unele metode care n superclas au o anumit implementare, n subclase s aib o alt implementare, adaptat la cerinele locale ale subclasei. class Angajat{ protected String nume; protected double sal_ora; public Angajat(String nume, double sal_ora) { this.nume = nume; this.sal_ora = sal_ora; } public double calcSalar(int nr_ore) { return (sal_ora * nr_ore); } public String toString() { return nume; } } class Sef extends Angajat { private double proc_cond; //procent de indemnizaie conducere public Sef(String nume, double sal_ora, double proc_cond) { super(nume, sal_ora); this.proc_cond = proc_cond; } public double calcSalar(int nr_ore) { return ((1 + proc_cond / 100) * sal_ora * nr_ore); } } class Client { public void oMetoda { Angajat a1 = new Angajat("Artaxerse Coviltir", 1000); Angajat a2 = new Sef("Al Bundy", 2000, 33.2); int ore_luna = 160; System.out.println("Salar " + a1 + "=" + a1.calcSalar(ore_luna));

} //. . .

System.out.println("Salar " a2.calcSalar(ore_luna));

a2

"="

Se observ c aceeai metod, calcSalar() apare att n clasa Angajat, ct i n clasa Sef, dar cu implementri diferite. Atunci cnd ntr-o subclas apare o metod avnd semntura identic cu o metoda din superclas, se spune c metoda din subclas o redefinete pe omonima ei din superclasa. n acest caz, un obiect al subclasei practic are dou exemplare ale metodei respective, unul motenit i unul propriu. Ce se ntmpl la nivelul clienilor ierarhiei? Se observ c n metoda oMetoda() din clasa Client se folosesc dou referine la Angajat: una indic un obiect al clasei Angajat, iar cealalt un obiect al clasei Sef. Prin intermediul celor dou referine se apeleaz metoda calcSalar(). Se pune problema care dintre cele dou forme ale metodei se apeleaz efectiv? n Java, regula care se aplic n asemenea cazuri este urmtoarea: Se va executa ntotdeauna acel exemplar de metod care este definit n clasa la care aparine obiectul concret indicat de referina utilizat. Aceast facilitate, adugat polimorfismului parial conduce la polimorfismul total. Cu alte cuvinte, clasa obiectului dicteaz i nu tipul referinei. Astfel, dei ambele referine a1 i a2 din exemplul considerat sunt de tip Angajat, ele indic, de fapt, obiecte ale unor clase diferite. Deci, apelul a1.calcSalar(...) va declana execuia metodei calcSalar() definit n clasa Angajat, iar apelul a2.calcSalar(...) va declana execuia metodei calcSalar() definit n clasa Sef. Polimorfismul total permite interschimbarea obiectelor indicate de o referin a superclasei, ntr-o manier transparent pentru clieni. n Java, clasa concret la care aparine un obiect indicat de o referin se cunoate, ns, abia la execuia programului. Deci, un apel de metod nu este rezolvat (adic pus n coresponden cu o implementare anume) la compilare, ci doar la execuie. Acest procedeu se numete legare dinamic sau amnat (late binding). S-a spus mai sus c un obiect al clasei Sef posed dou metode calcSalar(): cea motenit de la Angajat i cea local. Din cauz c n Java se aplic legarea dinamic, nseamn c, din perspectiva clienilor clasei Sef varianta local o eclipseaz pe cea motenit, neexistnd posibilitatea ca un client s foreze apelul metodei motenite (dect aplicnd o soluie ocolitoare, adic folosind o metod cu alt nume care s apeleze metoda calcSalar() motenit). n interiorul subclasei se poate realiza distincia ntre cele dou variante ale unei metode redefinite, i anume folosind simbolul super. Astfel, metoda calcSalar() din clasa Sef se poate folosi de omonima ei din clasa Angajat: class Sef extends Angajat { //. . . public double calcSalar(int nr_ore) { return ((1 + proc_cond / 100) * super.calcSalar(nr_ore)); } }

Practic, aceasta este singura situaie n care nu se aplic legarea dinamic, ci apelul de forma super.numeMetoda(...) este pus n coresponden exact cu implementarea din superclasa clasei curente.

Legarea dinamic i constructorii


Deoarece n Java la apelul metodelor non-statice se aplic legarea dinamic, pe de o parte, i innd cont de modul n care se apeleaz constructorii ntr-o ierarhie de clase, pe de alt parte, trebuie s avem grij cum proiectm constructorii dac acetia apeleaz la rndul lor metode ale claselor respective. class SuperClasa { protected int a; protected int rez; private int x; public SuperClasa( ) { a = 1; rez = 2; x = calcul( ); } public int calcul( ) { return (rez + a); } } class SubClasa extends SuperClasa { protected int b; private int y; public SubClasa( ) { b =3; y = calcul( ); } public int calcul( ) { return (rez * b); } } class Client { public void oMetoda { SubClasa ob = new SubClasa( ); //. . . } } S urmrim ce se ntmpl la crearea unui obiect al clasei Subclasa: innd cont de ordinea n care au loc iniializrile cmpurilor unui obiect, nseamn c se execut urmtorii pai: cmpurile a, rez, x, b i y se iniializeaz cu valorile implicite corespunztoare tipurilor lor, deci, n cazul nostru cu 0; se lanseaz constructorul SubClasa(); ca prim aciune a acestuia are loc apelul constructorului no-arg SuperClasa(); n constructorul SuperClasa() se execut iniializrile lui a i rez cu 1, respectiv 2, dup care se apeleaz metoda calcul(). n acest moment, apelul se leag de varianta metodei calcul() definit n clasa SubClasa, de care aparine obiectul n curs de iniializare. Efectul este

c x se va iniializ cu valoarea 2 * 0, adic cu 0, deoarece la momentul respectiv cmpul b nc nu a apucat s primeasc o alt valoare; se revine n constructorul SubClasa(), se iniializeaz b cu 3 i y cu 2*3 = 6, ct returneaz metoda calcul() din SubClasa. Dac n constructorul unei superclase se apeleaz o metod care este redefinit n subclas, la crearea unui obiect al subclasei exist riscul ca metoda respectiv s refere cmpuri neiniializate nc la momentul apelului.

Tem
Problema propus ncearc s dea o mn de ajutor n gestionarea produselor unei firme care comercializeaz echipamente electronice. Fiecare echipament este nregistrat cu un numr de inventar nr_inv, are un pre pret i este plasat ntr-o anumit zon din magazie zona_mag. Orice echipament poate fi ntr-una din situaiile: achiziionat (intrat n magazie); expus (expus n magazin); vndut (transportat i instalat la client). Firma comercializeaz mai multe tipuri de echipamente. Toate echipamentele care folosesc hrtia drept consumabil sunt caracterizate de numrul de pagini scrise pe minut ppm. Imprimantele sunt caracterizate de rezoluie (numr de puncte per inch dpi) i numr de pagini/cartu p_car. Unei imprimante i se poate seta modul de scriere: tiprireColor (selectere a modului color de tiprire); tiprireAlbNegru (selectere a modului alb-negru de tiprire). Copiatoarele sunt caracterizate de numrul de pagini/toner p_ton. Se poate seta formatul de copiere: setFormatA4 (setare a formatului A4); setFormatA3 (setare a formatului A3). Sistemele de calcul au un monitor de un anumit tip tip_mon, un procesor de o anumit vitez vit_proc, o capacitate a HDD c_hdd i li se poate instala: instalWin (instalarea unei variante de Windows); instalLinux (instalarea unei variante de Linux). Metodele specificate mai sus vor afia textul din parantez. De asemenea, fiecare metod va afia numrul de inventar al echipamentului. Se cere s se realizeze ierarhia de clase corespunztoare modelului prezentat, s se realizeze cteva echipamente i s se aplice operaiile posibile asupra lor. n momentul n care un client cumpr un echipament de la respectiva firm, trebuie verificat buna funcionare a echipamentului, prin apelul unei metode numit Functionare(TipEchipament e) unde e poate fi un echipament care folosete hrtia sau un sistem de calcul. Se cere ca firma s vnd diferite tipuri de echipamente, efectund pentru fiecare verificarea funcionrii astfel:
8

imprimant: tiprirea unei pagini color i a unei pagini alb-negru copiator: setare format A4 sistem de calcul: instalare Windows