Documente Academic
Documente Profesional
Documente Cultură
Curs – 5
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 :
- 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
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 .
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
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 :
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 :
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 :
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
import java.awt.Point;
class DreptunghiulMeu {
int x1=0;
int y1=0;
int x2=0;
int y2=0;
void afisareDreptunghi() {
System.out.print(“Dreptunghiul meu : <”+x1+”, “+y1);
System.out.println(“, “+x2+”, “+y2+”>”);
}
3
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 :
METODE CONSTRUCTOR
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 :
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 .
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
p.printPersoana();
System.out.Println(“----“);
p=new Persoana(“Laura”,30);
p.printPersoana();
System.out.println(“----“);
}
}
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 .
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 .
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
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 .
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 :
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 .
6
APELAREA METODEI ORIGINALE
De obicei exista doua motive pentru care se face suprascrierea unei metode implementate deja de o
superclasa :
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 :
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 .
// din AfisareClasa
void 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 AfisareSubClasa2
void 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
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 .
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 superclasei
else
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
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 :
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() .