Sunteți pe pagina 1din 7

M.

Joldo

ndrumtor de laborator

7. Motenire

Motenirea 1 super(...) constructorul superclasei (printelui)

Un obiect are cmpurile propriei clase plus cmpurile clasei printe, ale clasei bunic .a.m.d. pn sus la la clasa rdcin, clasa Object. Este necesar s iniializai toate cmpurile, de aceea trebuie invocai toi constructorii! Compilatorul Java insereaz automat apelurile de constructori necesare n procesul de nlnuire al constructorilor sau o putei face explicit. Compilatorul Java insereaz un apel la constructorul printelui (super) dac nu exist un apel de constructor ca prim instruciune al constructorului Dvs. Fiind dat codul care urmeaz
public class Point { int m_x; int m_y; //============ Constructor public Point(int x, int y) { m_x = x; m_y = y; } //============ Constructor implicit fara parametri public Point() { this(0, 0); // Apeleaza celalalt constructor. } . . . }

Cele ce urmeaz sunt echivalente cu constructorul de mai sus.


//============ Constructor (ca in apelul de mai sus) public Point(int x, int y) { super(); // realizat automat daca nu apelati constructorul. m_x = x; m_y = y; }

1.1

De ce ai dori s apelai explicit constructorul super

Exist dou situaii n care este necesar apelul explicit al constructorului superclasei: 1. Dorii s apelai constructorul cu parametri (apelul generat automat nu are parametri). 2. Nu exist un constructor fr parametri; sunt definii doar constructori cu parametri. n clasa printe. Fiecare obiect conine variabile instan ale clasei sale. Ceea ce nu este la fel de evident este c fiecare obiect are i toate variabilele instan ale tuturor superclaselor sale (ale tuturor strmoilor). Aceste variabile ale superclaselor trebuie iniializate nainte de a iniializa variabilele instana ale claselor. 1.1.1 Inserarea automat a apelului constructorului superclasei

La crearea unui obiect este nevoie s apelm toi constructorii tuturor superclaselor ca s-i iniializeze cmpurile proprii. Java face acest lucru automat la nceput dac nu-l facei Dvs. Spre exemplu, primul constructor Point ar fi putut fi scris

T.U. Cluj-Napoca

Programare orientat pe obiecte

M. Joldo

ndrumtor de laborator

7. Motenire

public Point(int xx, int yy) { super(); // inserat automat x = xx; y = yy; }

1.1.2

Apeluri explicite la constructorul superclasei

n mod normal nu se scrie explicit apelul constructorului superclasei adr exsit dou situaii cnd este necesar: Transmiterea parametrilor. Dorii s invocai un constructor al clasei printe care are parametri (constructorul implicit nu are parametri). Spre exemplu, dac definii o subclas a lui JFrame poate facei astfel:
class MyWindow extends JFrame { . . . //======== constructor public MyWindow(String title) { super(title); . . .

n exemplul de mai sus ai dorit s folosii constructorul lui JFrame care primete ca parametru titlul cadrului. Ar fi fost simplu s lsai s fie apelat constructorul implicit i s folosii o metod care seteaz titlul, ca alternativ.
class MyWindow extends JFrame { . . . //======== constructor public MyWindow(String title) { // constructorul implicit al superclasei este automat inserat setTitle(title); // apeleaz metoda din superclasa. . . .

Nu exist constructor fr parametri. Nu exist n printe un constructor fr parametri. Uneori nu are sens s crem un obiect fr a furniza parametri. Spre exemplu, ar trebuie ntr-adevr s existe un constructor Point fr parametri? Dei exemplul anterior a definit un constructor fr parametri pentru a ilustra folosirea lui this, nu este probabil o idee bun pentru Point. Exemplu de clas fr constructor fr parametri
/////////////////// clasa fara constructor fara parametri. // Daca este definit un constructor, compilatorul nu creaza automat un // constructor fara parametri. class Parent { int _x; Parent(int x) { // constructor _x = x; } } ////////////////// clasa care trebuie sa invoce super in constructor class Child extends Parent { int _y; Child(int y) { // GRESIT, este nevoie de apel explicit la super. _y = y; }

T.U. Cluj-Napoca

Programare orientat pe obiecte

M. Joldo

ndrumtor de laborator

7. Motenire

n exemplul de mai sus nu exist un apel explicit la un constructor n prima linie a constructorului, aa c compilatorul va insera un apel la un constructor fr parametri al printelui, dar aa ceva nu exist! De aceea, acest fapt duce la o eroare de compilare. Problema poate fi rezolvat prin schimbarea clasei Child.
////////////////// clasa care trebuie sa apeleze super in constructor class Child extends Parent { int _y; Child(int y) { // GRESIT, este nevoie de apel explicit la super. _y = y; } }

Sau clasa Parent poate defini un constructor fr parametri.


/////////////////// clasa fara constructor fara parametri. // Daca este definit un constructor, compilatorul nu creaza automat un // constructor fara parametri. class Parent { int _x; Parent(int x) { // constructor cu un parametru _x = x; } Parent() { // constructor fara parametri _x = 0; } }

O cale mai bun de a defini un constructor fr parametri este prin apelul unui constructor parametrizat astfel c orice schimbri sunt fcute ntr-un singur constructor.
Parent() { // constructor fara parametri this(0); } }

Remarcai c fiecare dintre aceti constructori apeleaz implicit constructorul fr parametri al printelui clasei sale . a. m. d. pn ce se ajunge n final la clasa Object. 1.1.3 Cum se suprascrie o metod?

Pentru a suprascrie o metod ntr-o clas nou, pur i simplu se reproduce numele, lista de argumente i tipul returnat al metodei originale ntr-o definiie nou de metod ntr-o nou clas. Apoi se scrie corpul metodei. Codul din corp se scrie astfel nct s fac comportamentul metodei suprascrise s fie corespunztor pentru un obiect din clasa nou. Iat o descriere mai precis a suprascrierii metodelor luat din cartea The Complete Java 2 Certification Study Guide, de Roberts, Heller i Ernest:

T.U. Cluj-Napoca

Programare orientat pe obiecte

M. Joldo

ndrumtor de laborator

7. Motenire

"O suprascriere valid are ordinea i tipul argumentelor identic, tip returnat identic i nu ete mai puin accesibil dect metoda original. Metoda care suprascrie nu trebuie s arunce nici o excepie verificat care nu a fost declarat pentru metoda original."
Orice metod nedeclarat final poate fi suprascris ntr-o subclas. 1.1.4 Suprascriere versus suprancrcare

Nu confundai suprascrierea cu suprancrcarea metodelor. Iat ce spun autorii menionai despre suprancrcarea metodelor:

"O suprancrcare valid difer ca numr sau tip de argumente. Diferenele de nume de argumente nu conteaz. Este permis un tip returnat diferit, dar acesta singur nu este suficient pentru a distinge o metod care suprancarc."

1.2
1.2.1

Probleme uzuale legate de motenire


Ascunderea variabilelor

Atunci cnd att clasa printe ct i subclasa au un cmp cu acelai nume, avem de a face cu ascunderea (engl shadowing) variabilei. Dac cmpul din clasa printe are acces private sau se afl in alt pachet i are acces implicit, nu e loc de confuzie. Clasa fiic nu poate accesa cmpul respectiv din clasa printe. Aa c e clar cu ce variabila se vor face operaiile n clasa fiic. Totui, dac o variabila cu acelai nume din clasa printe este accesibila instanelor clasei fiice, exist o serie de reguli ne-intuitive care determina care cmp este accesat de diferitele invocri. Regula general este c variabila accesat depinde de clasa la care s-a asignat tipul variabilei. Spre exemplu, Listing A conine doua clase, Base i Sub, care reprezint o relaie clas printe/clas copil. Ambele clase au un cmp ntreg numit field. Listing B ilustreaz instanierea clasei Sub urmat de mai multe modaliti legale de referire la una sau alta dintre variabilele field. Listing A public class Base
{ public int field = 0; public int getField() { return field; } } public class Sub extends Base { public int field = 1; public int getField() { return field; } }

Listing B
Sub s = new Sub(); Base b = s; System.out.println(s.field); // access one System.out.println(b.field); // access two System.out.println(((Sub)b).field); // access three System.out.println(((Base)s).field); // access four

Prima dintre aceste tehnici, marcat access one, acceseaz direct variabila field din instana lui Sub numit s. Acest acces, cum ne ateptam, d valoarea 1. Access two, ns, ilustreaz deconectarea logic implicat de ascunderea variabilei. Chiar dac expresia b==s este adevrat, cel de-al doilea acces, b.field, se evalueaz la 0.

T.U. Cluj-Napoca

Programare orientat pe obiecte

M. Joldo

ndrumtor de laborator

7. Motenire

Aceast diferen ntre b.field i s.field, n ciuda echivalenei de referire dintre b i s, arat clar cmpul minat inerent ascunderii variabilelor. Singura diferen dintre b i s n acest exemplu este tipul de variabil n care sunt stocate. Expresiile marcate access three i access four urmeaz regula de tip care dicteaz valoarea. Specific, access three d valoarea 1 deoarece obiectul b este convertit la tipul Sub nainte de verificarea variabilei sale field. Asemntor, access four d valoarea 0 datorit faptului c obiectul s este convertit la tipul Base nainte de accesul lui field. 1.2.2 Suprascrierea metodelor n timp ce cmpurile numite la fel din subclase ascund cele de acelai nume n clasele printe, se folosete o terminologie diferit pentru a trata probleme similare referitoare la metode. Atunci cnd o clas printe i o clas copil au fiecare o metod cu aceeai semntur, metoda din clasa copil suprascrie metoda din clasa printe. n Listing A, se poate vedea c metoda getField din clasa Sub are acelai nume i parametri adic nici un parametru ca metoda getField din clasa Base. Listing C
Sub s = new Sub(); Base b = s; System.out.println(s.getField); // access one System.out.println(b.getField); // access two System.out.println(((Sub)b).getField); // access three System.out.println(((Base)s).getField); // access four

Listing C ilustreaz aceeai instaniere de obiect ca Listing B i multe invocri posibile ale celor dou metode getField. Linia marcat access one din Listing C invoc metoda getField pe o referin la singurul obiect din exemplu stocat ntr-o variabil de tipul Sub. Cum a fost cazul din exemplul asemntor din Listing B, aceast invocare d valoarea 1. Diferena dintre suprascrierea metodei i ascunderea variabilei se observ la compararea lui access two din Listing C cu cel numit la fel din Listing B. Pe cnd n Listing B s-a accesat cmpul field al clasei printe, n Listing C este accesat variabila field din subclas, n ciuda tipului de variabil n care este stocat referina; rezult valoarea 1. Aceast aderare strict la identitatea referin/instan faa de tipul variabilei este sufletul polimorfismului. Polimorfismul este caracteristica care deleag comportamentul la clasa real a instanei referite nu la tipul n care este stocat referina. Polimorfismul este legat numai de metode. Continund cu exemplele, ajungem la access three i access four din Listing C. Amndou produc valoarea 1. Iari aceasta este din cauza naturii polimorfice a metodelor. Pentru a accesa variabila ascuns din clasa Base prin invocare de metod, trebuie folosit sintaxa super.field n clasa Sub.

2
2.1 2.2

Mersul lucrrii
Studiai textul i sursele prezentate n lucrare. Studiai i executai codul care urmeaz. Remarcai ordinea de iniializare.
class Insecta { private int i = 9; protected int j; Insecta() { System.out.println("i = " + i + ", j = " + j); j = 39; }

T.U. Cluj-Napoca

Programare orientat pe obiecte

M. Joldo

ndrumtor de laborator

7. Motenire

private static int x1 = printInit("static Insecta.x1 initializata"); static int printInit(String s) { System.out.println(s); return 47; } } public class Gindac extends Insecta { private int k = printInit("Gindac.k initializat"); public Gindac() { System.out.println("k = " + k); System.out.println("j = " + j); } private static int x2 = printInit("static Gindac.x2 initializat"); public static void main(String[] args) { System.out.println("Gindac constructor"); Gindac b = new Gindac(); } } /* Output: static Insect.x1 initialized static Gindac.x2 initialized Gindac constructor i = 9, j = 0 Gindac.k initialized k = 47 j = 39 */

2.3 2.4

2.5

2.6.

Adugai un alt tip de insect i apoi subclase ale lui Gindac i a tipului Dvs. Adugai cod pentru a arta ordinea operaiilor de iniializare pentru tipurile Dvs. Creai o ierarhie de mosteniri a lui Rozator: Soarece, Sobol, Hamster, etc. n clasa de baz, furnizai metode comune tuturor roztoarelor i suprascriei aceste metode n clasele derivate pentru a furniza comportamente specifice n funcie de tipul de Rozator. Creai un tablou de Rozator, umplei-l cu diferite tipuri de roztoare i apoi apelati metodele clasei de baz i studiai ce se ntmpl. Creai o clas abstract fr metode. Derivai din ea o clas i adugai o metod. Creai o metod static care primeste o referin spre clasa de baz, face "downcast" (forare de tip la un tip mai jos n ierarhia de tipuri) la clasa derivat i apeleaz metoda. n main( ), demonstrai c funcioneaz. Punei apoi declaraia abstract a metodei n clasa de baz eliminnd astfel nevoia de "downcast". Creai o taxonomie simpla pentru fiinele vii (cf. http://www.earthlife.net/insects/classtax.html), cu dezvoltare pe ramura insectelor. Exemplu:

T.U. Cluj-Napoca

Programare orientat pe obiecte

M. Joldo

ndrumtor de laborator

7. Motenire

FiintaVie

Planta

Ciuperca

Animal

Bacterie

Protoctista

Crustaceu

Miriapod

Insecta

Arahnida

Musca

Gindac

Phasmida

Dychoptera

Himenoptera

Lepidoptera

Instaniai obiecte de clasele respective. La instaniere, fiecare obiect i va dezvlui ascendena. D.e. Musca->Insecta->Animal->FiintaVie Arahnida->Animal->FiintaVie

T.U. Cluj-Napoca

Programare orientat pe obiecte

S-ar putea să vă placă și