Curs-5-Java

12
Programare Java Curs – 5 FOLOSIREA METODELOR PENTRU INDEPLINIREA SARCINILOR Metodele sunt partea cea mai importanta a oricarui limbaj de programare orientat obiect deoarece ele definesc fiecare actiune indeplinita de un obiect . Clasele si obiectele ofera un cadru de lucru . Variabilele de instanta si de clasa ofera o modalitate de a defini ceea ce reprezinta aceste clase si obiecte . Doar metodele pot defini comportamentul unui obiect – lucrurile pe care este capabil sa le realizeze sau modul cum interactioneaza cu alte clase sau obiecte . In cursurile anterioare am vazut cum sa definim o metoda si sa lucram cu ea practic . In continuare vom detalia unele caracteristici care fac metodele sa fie mai eficiente si mai usor de folosit : - supraincarcarea metodelor ( overloading ) – crearea de metode cu diferite semnaturi si definitii insa cu acelasi nume - crearea metodelor constructor – metode care permit initializarea obiectelor , pentru a le defini starea initiala din momentul crearii lor - suprascrierea metodelor (overriding ) – crearea unei definitii diferite penttu o metoda care a mai fost definita in superclasa - metode de finalizare ( finalizer ) – metode care elibereaza resursele ocupate de un obiect dupa terminarea lucrului cu un el , inainte ca acesta sa fie inlaturat din sistem CREAREA DE METODE CU ACELASI NUME SI ARGUMENTE DIFERITE Un exemplu de astfel de metoda este valueOf() ; metoda apartine clasei java.lang.String . In general in Java vom intalni des clase care contin mai multe metode cu acelasi nume . Metodele cu acelasi nume se diferentiaza intre ele prin doua caracteristici : - numarul argumentelor pe care le preiau - tipul datelor sau obiectelor fiecarui argument Aceste doua caracteristici definesc semnatura metodei ; folosirea mai multor metode cu acelasi nume si semnaturi diferite se numeste supraincarcare . In exemplul clasei String , metodele valueOf() sunt supraincarcate deoarece preiau ca parametri tipuri de date diferite . 1

Transcript of Curs-5-Java

Page 1: Curs-5-Java

Programare Java

Curs – 5

FOLOSIREA METODELOR PENTRU INDEPLINIREA SARCINILOR

Metodele sunt partea cea mai importanta a oricarui limbaj de programare orientat obiect deoarece ele definesc fiecare actiune indeplinita de un obiect .Clasele si obiectele ofera un cadru de lucru . Variabilele de instanta si de clasa ofera o modalitate de a defini ceea ce reprezinta aceste clase si obiecte . Doar metodele pot defini comportamentul unui obiect – lucrurile pe care este capabil sa le realizeze sau modul cum interactioneaza cu alte clase sau obiecte .In cursurile anterioare am vazut cum sa definim o metoda si sa lucram cu ea practic . In continuare vom detalia unele caracteristici care fac metodele sa fie mai eficiente si mai usor de folosit :

- supraincarcarea metodelor ( overloading ) – crearea de metode cu diferite semnaturi si definitii insa cu acelasi nume

- crearea metodelor constructor – metode care permit initializarea obiectelor , pentru a le defini starea initiala din momentul crearii lor

- suprascrierea metodelor (overriding ) – crearea unei definitii diferite penttu o metoda care a mai fost definita in superclasa

- metode de finalizare ( finalizer ) – metode care elibereaza resursele ocupate de un obiect dupa terminarea lucrului cu un el , inainte ca acesta sa fie inlaturat din sistem

CREAREA DE METODE CU ACELASI NUME SI ARGUMENTE DIFERITE

Un exemplu de astfel de metoda este valueOf() ; metoda apartine clasei java.lang.String . In general in Java vom intalni des clase care contin mai multe metode cu acelasi nume .

Metodele cu acelasi nume se diferentiaza intre ele prin doua caracteristici :

- numarul argumentelor pe care le preiau - tipul datelor sau obiectelor fiecarui argument

Aceste doua caracteristici definesc semnatura metodei ; folosirea mai multor metode cu acelasi nume si semnaturi diferite se numeste supraincarcare .In exemplul clasei String , metodele valueOf() sunt supraincarcate deoarece preiau ca parametri tipuri de date diferite .Supraincarcarea metodelor elimina nevoia de a defini metode complet diferite care sa faca in principiu acelasi lucru . Supraincarcarea face de asemenea posibila comportarea diferita a metodelor in functie de argumentele primite .Metodele valueOf() pot fi folosite pentru a converti diverse tipuri de date sau obiecte in siruri . Atunci cand apelam o metoda a unui obiect Java verifica numele si argumentele acesteia pentru a vedea ce metoda va executa .

Pentru a crea o metoda supraincarcata intr-o clasa vom defini metode diferite , cu acelasi nume insa cu liste de argumente diferite . Diferenta poate consta in numarul de argumente , in tipul de argumente sau ambele . Java permite supraincarcarea metodelor atat timp cat lista de argumente este unica pentru acelasi nume de metoda .Mentionez ca Java nu ia in considerare tipul valorii returnate pentru a face diferentierea metodelor supraincarcate . Daca incercam sa cream doua metode care difera doar prin tipul valorii de retur vom obtine o eroare inca de la compilare . In plus numele variabilelor pe care le alegem pentru fiecare argument nu au importanta – tot ceea ce conteaza este numarul si tipul acestora .

1

Page 2: Curs-5-Java

In continuare vom detalia un exemplu de metoda supraincarcata . Vom crea intai o clasa care defineste o forma rectangulara cu patru variabile de instanta , pentru a preciza colturile din stanga-sus si dreapta-jos ale unui dreptunghi : x1 , y1 , x2 , y2 .

class DreptunghiulMeu {int x1=0;int y1=0;int x2=0;int y2=0;}

Atunci cand este creata o noua instanta a clasei noastre toate valorile vor fi initializate cu 0 . In continuare vom defini o metoda care preia patru argumente intregi si returneaza obiectul rectangular . Deoarece argumentele au acelasi nume cu variabilele de instanta , in cadrul metodei vom folosi cuvantul cheie this pentru a referi variabilele de instanta :

DreptunghiulMeu construireDreptunghi ( int x1 , int y1 , int x2, int y2) {this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;return this;}

O alta varianta ar fi folosirea obiectelor Point in locul coordonatelor individuale . Pentru a implementa aceasta varianta putem supraincarca metoda noastra astfel incat lista de argumente sa contina doua obiecte Point :

DreptunghiulMeu construireDreptunghi ( Point stangaSus , Point dreaptaJos ) {x1=stangaSus.x;y1=stangaSus.y;x2=dreaptaJos.x;y2=dreaptaJos.y;return this;}

Pentru ca metoda anterioara sa functioneze clasa Point trebuie importata la inceputul codului sursa .

O alta modalitate de a defini un dreptunghi este de a folosi coordonatele coltului din stanga-sus impreuna cu valorile inaltimii si latimii sale :

DreptunghiulMeu construireDreptunghi(Point stangaSus , int l , int h ) {x1=stangaSus.x;y1=stangaSus.y;x2=(x1+l);y2=(y1+h);return this;}

Pentru a finaliza exemplul mai cream o clasa , afisareDreptunghi() , care urmeaza sa afiseze coordonatele dreptunghiului , si o metoda main() care sa apeleze toate aceste metode :

2

Page 3: Curs-5-Java

import java.awt.Point;

class DreptunghiulMeu {int x1=0;int y1=0;int x2=0;int y2=0;

DreptunghiulMeu construireDreptunghi(int x1 , int y1 , int x2 , int y2) {this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;return this;}

DreptunghiulMeu construireDreptunghi(Point stangaSus , Point dreaptaJos ) {x1=stangaSus.x;y1=stangaSus.y;x2=dreaptaJos.x;y2=dreaptaJos.y;return this;}

DreptunghiulMeu construireDreptunghi(Point stangaSus , int l , int h) {x1=stangaSus.x;y1=stangaSus.y;x2=(x1+l);y2=(y1+h);return this;}

void afisareDreptunghi() {System.out.print(“Dreptunghiul meu : <”+x1+”, “+y1);System.out.println(“, “+x2+”, “+y2+”>”);}

public static void main(String argumente[]) {DreptunghiulMeu dreptunghi=new DreptunghiulMeu();

System.out.println(“Apelam construireDreptunghi cu coordonatele 25,25,50,50 : “);dreptunghi.construireDreptunghi(25,25,50,50);dreptunghi.afisareDreptunghi();System.out.println(“***”);

System.out,println(“Apelam construireDreptunghi cu punctele (10,10) , (20,20): “);dreptunghi.construireDreptunghi(new Point(10,10, new Point(20,20));dreptunghi.afisareDreptunghi();System.out.println(“***”);

System.out.print(“Apelam construireDreptunghi cu 1 punct (10,10),”);System.out.println(“ latime 50 si inaltime 50 : “);dreptunghi.construireDreptunghi( new Point(10,10) , 50 , 50 );dreptunghi.afisareDreptunghi();System.out.println(“***”);}}

3

Page 4: Curs-5-Java

Atunci cand avem mai multe metode care fac lucruri asemanatoare , intr-o metoda putem apela o alta . De exemplu , in cazul de mai sus , metoda construireDreptunghi care primeste ca argumente doua obiecte Point poate fi inlocuita cu o versiune mult mai scurta :

DreptunghiulMeu construireDreptunghi(Point stangaSus , Point dreaptaJos) {return construireDreptunghi(stangaSus.x , stangaSus.y , dreaptaJos.x , dreaptaJos.y );}

METODE CONSTRUCTOR

In afara de metode obisnuite in clase putem defini si metode constructor .O metoda constructor este o metoda apelata la crearea unui obiect – cu alte cuvinte , atunci cand obiectul este construit .

Spre deosebire de alte metode , o metoda constructor nu poate fi apelata direct ; Java apeleaza metodele constructor in mod automat .Atunci cand este folosita instructiunea new pentru crearea unui nou obiect , Java executa trei activitati :

- aloca memorie pentru obiect- initializeaza variabilele de instanta ale obiectului fie la valorile initiale fie la cele prestabilite

( o pentru numere , null pentru obiecte , false pentru valori booleene si “\0” pentru caractere )- apeleaza metodele constructor ale clasei

Chiar daca o clasa nu are definita nici o metoda constructor este totusi posibila crearea unui obiect . Exista insa cazuri in care dorim sa setam anumite variabile de instanta sau sa apelam alte metode de care obiectul are nevoie pentru a se initializa . Prin definirea unor metode constructor in clase , putem seta valorile initiale ale variabilelor de instanta , putem apela metode pe bza acestor variabile , putem apela metode ale altor obiecte sau putem seta proprietatile initiale ale unui obiect . Metodele constructor pot fi si ele supraincarcate , la fel ca metodele obisnuite , pentru a crea un obiect care are proprietati specifice in functie de argumentele transmise prin instructiunea new .

METODE CONSTRUCTOR DE BAZA

Constructorii seamana cu netodele obisnuite , cu doua diferente :

- metodele constructor au totdeauna acelasi nume cu cel al clasei - metodele constructor nu returneaza nimic

In exemplul de mai jos vom vedea o clasa Persoana care foloseste o metoda constructor pentru a-si initializa variabilele de instanta pe baza argumentelor primite de new :

class Persoana {String nume;int varsta;Persoana (String n , int a) {nume=n;varsta=a;}void printPersoana() {System.out.print(“Eu sunt “+nume);System.out.println(“ si am “+varsta+” de ani”);}public static void main (String argumente[]) {Persoana p;p=new Persoana(“Ion”,50);

4

Page 5: Curs-5-Java

p.printPersoana();System.out.Println(“----“);p=new Persoana(“Laura”,30);p.printPersoana();System.out.println(“----“);}}

APELAREA UNEI ALTE METODE CONSTRUCTOR

Am vazut anterior cum o metoda poate apela o alta metoda in casrul ei .Acelasi lucru poate fi facut si in cazul constructorilor . Daca avem o metoda constructor ce reprezinta un comportament oarecum asemanator cu cel al unui constructor existent putem apela primul constructor din interiorul celui de-al doilea . Java ofera o sintaxa speciala pentru a realize acest lucru . Folosim urmatoarea instructiune pentru a apela o metoda constructor definite in clasa curenta :

this(arg1 , arg2 , arg3);

Folosirea cuvantului cheie this intr-o metoda constructor este similara modului lui de folosire pentru accesul la variabilele de instanta ale obiectului . In instructiunea anterioara argumentele primate de this() sunt argumentele metodei constructor . De exemplu , sa luam o clasa care defineste un cerc folosind coordonatele (x,y) ale centrului si lungimea razei . Clasa CerculMeu poate avea doi constructori : unul in care este definita raza si unul in care raza primeste valoarea prestabilita 1 :

class CerculMeu {int x,y,raza;CerculMeu (int coordX , int coordY , int lungRaza) {this.x=coordX;this.y=coordY;this.raza=lungRaza;}CerculMeu (int coordX , int coordY) {this(coordX, coordY, 1);}}

A doua metoda constructor din clasa CerculMeu preia doar coordonatele x si y ale cercului . Deoarece nu este definite nici o raza se foloseste valoarea prestabilita 1 ; se apeleaza apoi prima metoda constructor care primeste ca argumente coordX , coordY si literalul 1 .

SUPRAINCARCAREA METODELOR CONSTRUCTOR

Ca si metodele obisnuite constructorii pot avea un numar diferit de argumente sau tipuri ale acestora . Aceasta ne permite sa cream un obiect cu proprietatile dorite sau ofera acestuia posibilitatea de a-si calcula proprietatile pornind de la date de intrare diferite .

De exemplu , metodele construireDreptunghi , definite in exemplele anterioare , pot constitui niste metode constructor foarte logice deoarece sunt folosite pentru a initializa variabilele de instanta . Astfel , in loc de metoda originala construireDreptunghi ( care primea patru parametric ) am putea crea un constructor .

SUPRASCRIEREA METODELOR

Atunci cand apelam metoda unui obiect , Java cauta definitia metodei respective in clasa obiectului . Daca nu o gaseste cauta mai sus in ierarhia de clase pana cand gaseste o definitie . Procesul de

5

Page 6: Curs-5-Java

mostenire a metodelor ne permite sa definim si sa folosim repetat metode in subclase fara a fi nevoie sa replicam codul .Totusi pot exista cazuri cand dorim ca un obiect sa raspunda acelorasi metode , dar sa aiba un comportament diferit la apelarea acestora . In acest caz , metoda se poate suprascrie . Pentru a suprascrie o metoda , definim intr-o subclasa o metoda cu aceeasi semnatura ca a unei metode dintr-o superclasa . Astfel , atunci cand metoda este apelata , metoda din subclasa este gasita prima si executata in locul celei din superclasa .

CREAREA DE METODE CARE SUPRASCRIU METODE EXISTENTE

Pentru a suprascrie o metoda , in practica trebuie sa cream o metoda cu aceeasi semnatura ( nume , tip , valoare returnata , lista de argumente ) ca a metodei din superclasa . Mai jos cream un exemplu pentru a ilustra supraincarcarea unei metode :

class AfisareClasa {int x=0;int y=0;void afisareDate() {System.out.println(“x este “+x+” si y este “+y);System.out.println(“Sunt o instanta a clasei “+this.getClass().getName());}}

Cream in continuare si o subclasa a clasei de mai sus , cu o singura diferenta , subclasa contine si variabila z :

class AfisareSubClasa extends AfisareClasa {int z=3;public static void main(String argumente[]) {AfisareSubClasa obiect=new AfisareSubClasa();obiect.afisareDate();}}

Deoarece subclasa nu defineste o metoda afisareDate() , Java o cauta in superclasa si o gaseste acolo pentru a o putea executa . Aceasta metoda insa nu afiseaza si variabila de instanta z .

Sa cream o noua subclasa care sa suprascrie metoda afisareDate() :

class AfisareSubClasa2 extends AfisareClasa {int z=3;void afisareDate() {System.out.println(“x este “+x+” si y este “+y+” iar z este “+z);System.out.println(“Sunt o instanta a clasei “+this.getClass().getName());}public static void main(String argumente[]) {AfisareSubClasa2 obiect=new AfisareSubClasa2();obiect.afisareDate();}}

Acum , dupa initializarea obiectului AfisareSubClasa2 si apelarea metodei afisareDate() va fi apelata versiunea existenta in subclasa si nu pe cea din superclasa AfisareDate .

6

Page 7: Curs-5-Java

APELAREA METODEI ORIGINALE

De obicei exista doua motive pentru care se face suprascrierea unei metode implementate deja de o superclasa :

- pentru a inlocui complet definitia metodei originale - pentru a extinde functionalitatea metodei originale

In multe cazuri practice comportamentul metodei originale trebuie doar completat si nu inlocuit definitiv , mai ales in cazurile cand se realizeaza acelasi tip de actiuni si in metoda originala si in cea care o suprascrie . Prin apelarea metodei originale in cadrul metodei de suprascriere putem adauga numai insusirea suplimentara .Pentru a apela metoda originala in cadrul metodei de suprascriere folosim cuvantul cheie super . In acest fel apelul metodei este transferat mai sus in cadrul ierarhiei de obiecte :

void metodaMea ( String a , String b ) {//cod sursasuper.metodaMea(a,b);//cod sursa}

Cuvantul cheie super este asemanator cuvantului cheie this , deoarece este o denumire generica pentru superclasa clasei curente . Il putem folosi oriunde am putea folosi si this , insa super refera superclasa nu clasa curenta .

Sa ne amintim de cele doua metode afisareDate() diferite , folosite anterior . In loc sa copiem majoritatea codului metodei superclasei in subclasa , putem modifica metoda superclasei astfel incat ulterior sa se poata adauga cu usurinta o caracteristica suplimentara :

// din AfisareClasavoid afisareDate() {System.out.println(“Sunt o instanta a clasei “+this.getClass().getName());System.out.println(“X este “+x);System.out.println(“Y este “+y);}

Apoi , cand suprascriem metoda afisareDate() in subclasa putem apela metoda originala si adauga doar codul suplimentar :

// din AfisareSubClasa2void afisareDate() {super.afisareDate();System.out.println(“Z este “+z);}

SUPRASCRIEREA CONSTRUCTORILOR

Din punct de vedere tehnic constructorii nu pot fi suprascrisi . Pentru ca au totdeauna acelasi nume ca al clasei curente , metodele constructor nu se mostenesc ci se creaza altele noi . Acest sistem este multumitor in marea majoritate a cazurilor ; atunci cand este apelata metoda constructor a clasei se apeleaza si metoda constructor cu aceeasi semnatura pentru toate superclasele . Din aceasta cauza initializarea se face pentru toate partile clasei pe care o mostenim .

7

Page 8: Curs-5-Java

Totusi , atunci cand definim metode constructor pentru clasa noastra putem modifica felul in care este initializat obiectul nu doar prin initializarea noilor variabile adaugate clasei , ci si prin modificarea continutului variabilelor deja prezente . Pentru aceasta vom apela explicit metodele constructor ale superclasei si apoi vom modifica variabilele dorite .

Pentru a apela o metoda obisnuita apartinand superclasei vom folosi sintaxa super.nume_metoda(lista_argumente) . Deoarece metodele constructor nu au nume sub care pot fi apelate vom folosi urmatoarea forma :

super(arg1 , arg2 , ... );

Retinem ca Java are o regula stricta pentru folosirea metodei super() : aceasta trebuie sa sie prima instructiune folosita in cadrul constructorului . Daca nu apelam super() explicit in cadrul constructorului Java face acest lucru implicit , folosind super() fara argumente . Deoarece apelarea super() trebuie sa fie prima instructiune nu putem folosi un cod de genul :

if (conditie==true) super(1 , 2 , 3); // apelarea unui constructor al superclaseielse super( 1 , 2 ); // apelarea unui alt constructor

La fel ca in folosirea this(...) intr-o metoda constructor , super(...) apeleaza metoda constructor pentru superclasa imediat urmatoare ( care la randul sau va apela constructorul superclasei sale si asa mai departe ) . Retinem ca in superclasa trebuie sa existe un constructor cu semnatura respectiva pentru ca apelul super() sa functioneze . Compilatorul Java verifica aceste lucruri atunci cand incercam sa compilam fisierul sursa .

Nu trebuie sa apelam constructorul din superclasa care are aceeasi semnatura cu cea a constructorului clasei noastre ; trebuie doar sa apelam constructorul pentru valorile pe care dorim sa le initializam . De fapt , putem crea o clasa care are constructori cu semnaturi total diferite de oricare dintre constructorii superclasei .

In exemplul urmator vom prezenta o clasa PunctCuNume care extinde clasa Point a pachetului java.awt . Clasa Point are un singur constructor care preia argumentele x si y si returneaza un obiect Point . PunctCuNume contine o variabila de instanta suplimentara si defineste un constructor care initializeaza x , y si numele .

import java.awt.Poin;class PunctCuNume ( int x , int y , String nume ) {super(x,y);this.nume=nume;}public static void main(String argumente[]) {PunctCuNume pn=new PunctCuNume(5,5,”PunctulA”);System.out.println(“x este “+pn.x);System.out.println(“y este “+pn.y);System.out.println(“Numele este “+pn.nume);}}

Metoda constructor definita aici pentru PunctCuNume apeleaza metoda constructor a clasei Point pentru a initializa variabilele de instanta x si y . Chiar daca am putea initializa si singuri , explicit , variabilele x si y exista posibilitatea sa existe si alte lucruri care s-ar intampla la initilizarea obiectelor Point ; din aceasta cauza este mai bine sa apelam metodele constructor aflate deasupra in ierarhie , pentru a fi siguri ca totul se configureaza corect .

8

Page 9: Curs-5-Java

METODE DE FINALIZARE

Metodele de finalizare sunt opusul metodelor constructor . O metoda constructor este folosita pentru a initializa un obiect iar metodele de finalizare sunt apelate chiar inainte de distrugerea obiectului si recuperarea memoriei ocupate .

Metoda de finalizare este finalize() . Clasa Object defineste o metoda de finalizare prestabilita , care nu face nimic ( este vida ) . Pentru a crea o metoda de finalizare pentru propriile clase putem suprascrie metoda finalize() folosind semnatura :

protected void finalize() throws Throwable {super.finalize();}

In cadrul metodei finalize() putem specifica toate actiunile de “curatare” pe care dorim sa le realizam in legatura cu obiectul . De asemenea putem apela super.finalize() pentru a permite superclasei clasei noastre sa finalizeze obiectul daca este nevoie .Putem apela metoda finalize() oricand – este o metoda ca oricare alta . Totusi apelarea ei nu semnaleaza sistemului distrugerea obiectului si recuperarea memoriei ocupate . Numai stergerea tuturor referintelor la obiectul respectiv duce la marcarea lui pentru distrugere .Metodele de finalizare sunt folosite de obicei pentru optimizarea distrugerii unui obiect – de exemplu , pentru distrugerea referintelor catre alte obiecte . In marea majoritate a cazurilor practice nu este nevoie se folosim deloc metoda explicita finalize() .

9