Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Tipuri de date. Clase si obiecte

java


Tipuri de date. Clase si obiecte 



Tipuri primitive 

In limbajul Java avem la dispozitie urmatoarele tipuri primitive de date

  • boolean: este format din 2 valori: true si false 
  • byte: este multimea numerelor intregi cu semn reprezentabile pe 8 biti; 
  • short: este multimea numerelor intregi cu semn reprezentabile pe 16 biti; 
  • int: este multimea numerelor intregi cu semn reprezentabile pe 32 biti 
  • long: este multimea numerelor intregi cu semn reprezentabile pe 64 biti 
  • float: este multimea numerelor reale simpla precizie reprezentabile pe 32 biti 
  • double: este multimea numerelor reale dubla precizie reprezentabile pe 64 biti 
  • char: este multimea caracterelor codificate in sistem Unicode, pe 16 biti; practic sistemul Unicode vine sa extinda sistemul ASCII (in care caracterele sunt reprezentate pe 1 octet), pentru a include un numar mai mare de caractere speciale, cum ar fi literele arabe sau chinezesti, litere din limbile slave, litere cu diverse accente asociate etc. 

In ceea ce priveste tipurile numerice (intregi si reale), cu ajutorul exemplului de mai jos puteti afla care sunt limitele maxime pentru fiecare. Pentru a putea intelege pe deplin exemplul, va trebui sa aveti putintica rabdare, pana ajungem la capitolul cu clasele infasuratoare. Deocamdata tot ce aveti de facut este sa compilati si sa executati programul: 
 

MaxVariablesDemo.java
// Aplicatie ce afiseaza valorile limita

public class MaxVariablesDemo  
else  
System.out.println("Valoarea variabilei aBoolean este " + aBoolean); 

Daca vreti sa aflati si limitele minime pentru tipurile numerice trebuie sa inlocuiti in exemplul de mai sus simbolul MAX_VALUE cu MIN_VALUE si apoi sa rulati programul. 

Asa dupa cum stim, tipurile sunt folosite pentru a putea declara variabile. Indiferent ca e vorba de tipuri primitive sau nu, intr-un program Java putem avea declaratii de variabile in urmatoarele locuri: 

  • in interiorul claselor, caz in care variabilele sunt campuri sau date membru ale claselor respective; 
  • in listele de parametri formali din antetul functiilor; 17517s1817r un exemplu in acest sens este args, parametrul functiei main (parametru care nu e de tip primitiv); 
  • in interiorul functiilor, caz in care variabilele sunt variabile locale ale functiilor respective; in exemplul de mai sus toate variabilele sunt variabile locale ale functiei main

Despre functiile dintr-un program Java vom vorbi mai pe larg in modulul urmator, iar despre variabile care nu sunt de tipuri primitive vom vorbi in capitolul despre Crearea obiectelor

In afara de variabile, intr-un program Java putem intalni si constante literale. In cele ce urmeaza, prin cateva exemple vom arata cum se scriu constantele pentru fiecare tip primitiv: 

  • numere intregi: 124, 45635 etc.; compilatorul de Java asimileaza orice asemenea constanta ca fiind de tipul int
  • numere intregi de tip long: 8864L, 125363646L; 
  • numere reale: 12.4, 26.77e-2; compilatorul de Java asimileaza orice asemenea constanta ca fiind de tipul double. Programatorul poate scrie si explicit o constanta reala de tip double: 456.34D; 
  • numere reale de tip float: 87.353F; 
  • constante de tip char: 'n', 'G', '%', '\'' (caracterul apostrof), '\n' (caracterul salt la linie noua); 


constantele de tip boolean: true si false. 

Tipuri definite de utilizator: clase

Asa cum am aratat in primul modul, unul din principalele avantaje aduse de limbajele de programare OO il constituie posibilitatea utilizatorului de a-si defini propriile tipuri. Aceste tipuri sunt de fapt clasele. 

O clasa reprezinta descrierea unei multimi de obiecte care au aceeasi structura si acelasi comportament.

Ca urmare, intr-o clasa vom gasi definitiile datelor si ale operatiilor (functiilor) ce caracterizeaza obiectele clasei respective. 
Datele definite intr-o clasa se mai numesc date-membru, variabile-membru, atribute sau campuri, iar operatiile se mai numesc metode sau functii-membru.
Constructia sintactica folosita pentru a defini o clasa in Java este

class nume_clasa

Pentru a prezenta modul in care definim membrii dintr-o clasa, vom utiliza urmatorul exemplu concret: 
 

class Punct 

public void move(int dx, int dy)  

public int getX( )  

public int getY( )  

Clasa Punct modeleaza un punct de pe ecranul unui monitor si are ca date-membru 2 variabile de tip int: x si y reprezentand coordonatele punctului, iar ca metode:

  • functia init care initializeaza coordonatele punctului; 
  • functia move care deplaseaza un punct pe o anumita distanta; 
  • functiile getX si getY care returneaza coordonatele curente ale punctului. 

Se observa ca definitiile datelor si ale functiilor din interiorul clasei sunt prefixate de anumite cuvinte cheie, ca public si private, care se numesc modificatori de acces. Vom vedea putin mai jos care este rolul acestora. 

In limbajele de POO clasele pot fi considerate ca mecanisme prin care programatorul isi construieste propriile sale tipuri de date, pe care apoi le va folosi aproape la fel cum foloseste tipurile predefinite. 
Cu alte cuvinte: 

Clasa este un tip de date si ca atare, unul dintre rolurile ei fundamentale este acela de a servi la declararea variabilelor.
Valorile unui tip clasa se numesc obiecte sau instante ale clasei respective.

Pentru a avea o imagine mai clara a diferentei dintre o clasa si un obiect vom considera urmatorul exemplu luat din matematica: daca dorim sa descriem multimea formata din numerele naturale mai mari decat 5 vom scrie: 

M5 =

Valoarea 10 este un element particular al multimii M5
In cazul unui program OO, clasa este similara lui M5, adica este o descriere a unei multimi, in timp ce obiectul este un element particular al multimii respective. Generalizand, vom spune ca intr-un program: 

Tipurile sunt multimi, iar constantele si valorile variabilelor sunt elemente ale respectivelor multimi. 

Daca luam exemplul clasei Punct, putem spune ca ea descrie multimea tuturor obiectelor caracterizate prin 2 coordonate intregi si prin posibilitatea de a executa operatiile definite in clasa Punct. Un element particular al acestei multimi se obtine dand valori concrete coordonatelor x si y

Observatie: si tipurile primitive ale unui limbaj de programare reprezinta tot multimi, dar care nu au o descriere explicita, ci una subinteleasa, derivata din modul de reprezentare interna a valorilor tipurilor respective. De exemplu, in Java tipul short este multimea numerelor intregi reprezentabile pe 2 octeti. 

Crearea obiectelor 

In cele ce urmeaza vom considera un mic program Java care foloseste clasa Punct prezentata mai sus, pentru a vedea cum se creaza obiecte ale acestei clase: 
 

class Punct 

public void move(int dx, int dy)  

public int getX( )  

public int getY( )  

class ClientPunct  

Variabilele p1 si p2 sunt referinte la obiecte de tip Punct
In Java orice variabila al carei tip este o clasa constituie o referinta, adica o variabila ale carei valori sunt adrese de memorie. La adresele respective se vor afla obiecte ale clasei care reprezinta tipul referintei. Spunem ca referinta indica spre un obiect
Obiectul indicat de o referinta nu apare automat, prin simpla declarare a referintei, ci el trebuie creat.
De fapt lucrurile se intampla asa: intai se creaza obiectul si apoi adresa de memorie unde el a fost pus este atribuita referintei. 

Nu este suficient sa declaram: 

Punct p1;

deoarece acest lucru este echivalent cu a declara o variabila pe care nu o initializam cu nici o valoare. 
In programul de mai sus se poate observa modul in care are loc crearea unui obiect, si anume, prin aplicarea operatorului new, care se mai numeste operator de alocare

p1 = new Punct( );

Efectul acestui operator este urmatorul: in memorie se aloca un spatiu necesar pentru stocarea unui obiect al clasei Punct, iar adresa zonei alocate se returneaza ca valoare. 
Vom vedea ceva mai incolo (la capitolul despre constructori) ce semnificatie are constructia Punct( ) care apare in contextul operatorului new
Dupa initializare, referintele vor putea fi folosite pentru a apela metodele obiectelor create. Notatia prin care se realizeaza un apel de metoda este: 

nume_referinta . nume_metoda ( lista_parametri_actuali )

In figura de mai jos este reprezentata in mod intuitiv imaginea in memorie a celor 2 obiecte create in program: 

Se observa ca in interiorul obiectelor am figurat atat datele cat si functiile. Putem sa ne imaginam ca acele date si functii exista in atatea exemplare, cate obiecte sunt create in program la un moment dat. 
Poate va intrebati de ce in figura apar cuvintele "stiva" si "heap". Aici trebuie spus ca variabilele locale ale metodelor sunt alocate in mod static, iar zona de memorie utilizata in acest scop este exploatata in regim de stiva. 
In ceea ce priveste obiectele, ele sunt create in mod dinamic, iar zona de memorie utilizata pentru alocari dinamice se mai numeste heap (gramada). 

In cazul unui apel de forma p1.init(. . .) se mai spune ca se apeleaza metoda init pentru obiectul referit de p1, sau ca obiectul referit de p1 receptioneaza cererea (mesajul) de a executa operatia init. De aceea, cand vom prezenta anumite metode, vom utiliza frecvent denumirea de obiect receptor ca sa desemnam obiectul care detine metodele respective. 

Nu intamplator am numit clasa principala din programul nostru ClientPunct: aceasta clasa (prin intermediul metodei main) solicita unor obiecte ale clasei Punct sa execute anumite functii sau, altfel spus, solicita prestarea unor servicii. 
Spunem in acest caz ca obiectele clasei Punct sunt obiecte server, iar ClientPunct este clientul lor. 
Practic, interactiunile dintre obiecte se bazeaza pe conceptul de client-server: obiectul care apeleaza o metoda este clientul, iar obiectul care contine metoda respectiva este serverul. 

Reguli de vizibilitate

Am vazut ca in definitiile membrilor unei clase se utilizeaza niste cuvinte speciale, numite modificatori de acces. Acestia stabilesc drepturile de acces ale clientilor la membrii unei clase. 
Cand discutam despre drepturile de acces la membrii unei clase trebuie sa abordam acest subiect din 2 perspective: 

1. Interiorul clasei sau, mai concret, metodele clasei.In cadrul metodelor unei clase exista acces nerestrictiv la toti membrii, date sau functii. De exemplu, in metodele clasei Punct se face referire la campurile x si y. In mod asemanator s-ar fi putut referi (apela) si metodele. De exemplu, am fi putut defini functia move pe baza functiei init astfel: 

class Punct 

Se observa ca in interiorul clasei nu se foloseste notatia cu punct pentru a referi membrii, acestia fiind pur si simplu accesati prin numele lor. Cand o metoda face referire la alti membri ai clasei, de fapt sunt accesati membrii corespunzatori ai obiectului receptor, indiferent care ar fi el. De exemplu, cand se apeleaza metoda init a obiectului referit de p1, are loc initializarea membrilor x si y ai acelui obiect. 
In legatura cu accesul din interiorul unei clase, trebuie spus ca absenta restrictiilor se aplica si daca este vorba despre membrii altui obiect din ACEEASI clasa, dar diferit de cel receptor. De exemplu, daca in clasa Punct am avea cate o metoda de calcul al distantei pe vericala/orizontala dintre 2 puncte, unul fiind obiectul receptor, iar celalalt un obiect dat ca parametru, atunci am putea scrie: 
 

class Punct 

public int distH(Punct p)  

Se observa ca din interiorul metodelor distV / distH putem accesa liber membrii privati ai obiectului p dat ca parametru. La fel ar sta lucrurile si daca p ar fi o variabila locala a unei metode din clasa Punct

Observatie: in fraza de mai sus am utilizat expresia "obiectul p"; de fapt, corect este "obiectul indicat de p". Din motive de simplificare a exprimarii insa, de acum inainte, acolo unde nu exista riscul unei confuzii, vom "imprumuta" obiectului numele referintei. 
 

  • 2. Exteriorul sau clientii clasei. Clientii unei clase pot accesa doar acei membri care au ca modificator de acces cuvantul public. Membrii declarati cu modificatorul private NU sunt vizibili in afara, sunt ascunsi. Daca am incerca sa folosim in metoda main din exemplul nostru o referinta de genul: 

p1.x

compilatorul ar raporta o eroare. 

O observatie importanta pe care o putem desprinde din exemplul clasei Punct este aceea ca structura unei clase, sau modul ei de reprezentare, care este dat de variabilele membru, de regula se ascunde fata de clienti. Daca este necesar ca acestia sa poata consulta valorile datelor membru, se va opta pentru definirea unor metode de genulgetValoare, iar nu pentru declararea ca publice a datelor respective.

Intr-o clasa Java putem declara membri care sa nu fie precedati de nici un modificator de acces. In acest caz, membrii respectivi se spune ca sunt accesibili la nivel de pachet ("package"), adica sunt vizibili de catre toti clientii aflati in acelasi pachet cu clasa in cauza. 
De asemenea, mai exista un modificator de acces, protected, utilizat in contextul ierarhiilor de clase. Despre el vom vorbi cand vom invata despre mostenire. 

Initializarea campurilor unui obiect. Constructori

Am vazut in exemplul cu ClientPunct ca dupa crearea obiectelor p1 si p2, pentru ele s-a apelat metoda init care avea drept scop initializarea campurilor x si y respectiv ale celor 2 obiecte. Practic, metoda init poate constitui un exemplu de mod de initializare a campurilor unui obiect, dar nu este cel mai bun. De exemplu, un repros care i se poate aduce este acela ca programatorul ar putea omite apelul metodei, caz in care campurile vor avea alte valori (vom vedea care) decat cele dorite. 
La definirea unei clase in Java, programatorul poate prevedea una sau mai multe metode speciale, numite constructori, al caror scop este tocmai initializarea datelor unui obiect imediat dupa ce el a fost creat. Vom ilustra, tot cu ajutorul clasei Punct, modul de specificare a constructorilor: 
 

class Punct 

public Punct(Punct p)  

Cele 2 metode declarate in secventa de mai sus se numesc constructori. Iata care sunt caracteristicile unui constructor: 

  • este o metoda care are acelasi nume cu clasa in care este definita; 
  • NU are tip returnat (nici macar void); 
  • se apeleaza in mod automat la crearea unui obiect. 

Astfel, in loc sa folosim metoda init, in functia main din clasa ClientPunct am fi putut scrie: 
 

class ClientPunct 

Deci, dand parametrii doriti, la crearea celor 2 instante automat vor intra in executie constructorii corespunzatori, astfel incat este eliminat riscul omiterii initializarii. 

Am vazut ca intr-o clasa putem avea mai multi constructori. De fapt, acest lucru este un efect al facilitatii de supraincarcare a functiilor existenta in limbajul Java. 

Prin supraincarcare se intelege posibilitatea de a defini in acelasi domeniu de vizibilitate mai multe functii cu acelasi nume, dar cu parametri diferiti ca tip si/sau numar

NU se permite ca functiile supraincarcate sa difere DOAR prin tipul returnat. 
In exemplul nostru am definit 2 constructori: unul cu 2 parametri de tip int, iar celalalt cu un parametru de tip Punct. Am putea atunci sa mai cream o instanta a clasei Punct, sub forma: 

Punct p3 = new Punct(p1);

caz in care obiectul referit de p3 ar avea aceleasi valori ale coordonatelor ca si obiectul referit de p1

Intrebare: avand in vedere ca p3 si p1 sunt referinte, ce s-ar fi intamplat daca am fi scris: 

Punct p3 = p1;

in loc de fraza de mai sus? 

Atunci cand un constructor nu are parametri el se numeste constructor no-arg

Daca programatorul nu prevede intr-o clasa NICI UN constructor, atunci compilatorul va insera automat in clasa respectiva un constructor implicit de tip no-arg si al carui corp de instructiuni este vid. 

Asa au stat lucrurile in cazul primei definitii a clasei Punct. Astfel se explica de ce la crearea unui obiect Punct am folosit notatia: 

p1 = new Punct ( );

Practic, aici am apelat constructorul implicit generat automat de compilator. 

Daca programatorul include intr-o clasa CEL PUTIN un constructor, indiferent de care, compilatorul NU va mai genera constructorul implicit pentru acea clasa.

Astfel, in definitia clasei Punct care include cei 2 constructori descrisi mai inainte nu avem constructor implicit, dar nici constructor no-arg. Ca urmare, daca incercam sa scriem: 

p1 = new Punct ( );

compilatorul va semnala eroare, in sensul ca nu exista vreo definitie de constructor care sa nu aiba parametri. 
In legatura cu constructorii trebuie spus ca, exceptand anumite cazuri deosebite, ei vor trebui sa aiba modificatorul de acces public. Altfel, nu vom putea crea obiecte ale claselor respective. 

Alte metode de initializare a campurilor unei clase

Pe langa constructori, limbajul Java mai ofera si alte posibilitati de a initializa campurile unei clase: 

Initializatori la declarare, care pot fi impliciti sau expliciti

class Punct 


Punct p1 = new Punct(); //in acest caz p1.x = 0 si p1.y=1 

Initializatorii impliciti depind de tipul campului respectiv, si anume: sunt 0 pentru tipurile numerice, false pentru tipul boolean si null pentru referinte la obiecte. 

Atentie! Initializarile implicite nu se aplica si in cazul variabilelor locale ale metodelor. Acestea trebuie initializate explicit de catre programator. 

Blocuri de initializare: sunt secvente de cod cuprinse intre acolade, plasate imediat dupa declaratia campului pe care il initializeaza, si care pot fi asimilate cu niste constructori no-arg. Ele se folosesc atunci cand valoarea de initializare a unui camp nu este o constanta simpla, ci trebuie obtinuta prin calcule. 
Ca exemplu vom presupune ca variabila x din clasa Punct trebuie initializata cu valoarea sumei primelor 6 numere Fibonacci: 
 

class Punct 

Pentru o clasa in care apar mai multe mecanisme de initializare, ordinea lor de aplicare este urmatoarea: 

    1. Initializatorii din declarare. 
    2. Blocurile de initializare, in ordinea textuala in care ele apar in interiorul clasei. 
    3. Constructorii. 


Deosebirea esentiala intre constructori si celelalte tipuri de initializari este aceea ca, in cazul constructorilor putem initializa fiecare instanta cu valori diferite pe care le dam ca parametri. Celelalte mecanisme de initializare presupun ca toate instantele clasei vor fi initializate cu aceleasi valori in campurile respective.

Membrii statici ai claselor

Pana acum, in clasa Punct am definit doar membri non-statici. Acestia se mai numesc si membri ai instantelor, deoarece, asa cum am vazut si in figura prezentata mai la inceputul acestui material, fiecare instanta isi are propriile exemplare ale membrilor respectivi. 
Limbajul Java permite definirea unei categorii speciale de membri, numiti statici sau membri de clasa. Acesti membri vor exista in exemplare unice pentru fiecare clasa, fiind accesati in comun de toate instantele clasei respective. Mai mult, membrii statici pot fi referiti chiar si fara a instantia clasa, ei nedepinzand de obiecte. 
Pentru a defini un membru static se utilizeaza cuvantul cheie static, plasat dupa modificatorul de acces: 

modificator_acces static tip_membru nume_membru ;

Referirea unui membru static NU se va face prin intermediul numelui obiectului, ci prin intermediul numelui clasei: 

nume_clasa . nume_membru_static

Pentru exemplificare vom modifica clasa Punct astfel incat sa putem calcula numarul de apeluri ale metodei move pentru TOATE obiectele create intr-un program. Pentru aceasta vom defini o variabila statica contor si o metoda statica getContor
 

class Punct 

public void move(int dx, int dy)  

public static int getContor()  

//metoda main din clasa radacina 
Punct p1 = new Punct(10,20); 
Punct p2 = new Punct(15,13); 

p1.move(8,-2); p2.move(6,7); 

System.out.println("S-au executat "+Punct.getContor()+" mutari."); 

In figura de mai jos este reprezentata in mod intuitiv imaginea in memorie a celor 2 obiecte create in programul de mai sus: 

In legatura cu membrii statici ai unei clase trebuie facuta urmatoarea observatie: 

Intr-o metoda statica NU este permisa referirea simpla a unui membru non-static. Acest lucru se explica prin aceea ca un membru non-static exista doar in interiorul unui obiect, pe cand membrii statici exista independent de obiecte.

Daca in exemplul nostru am fi declarat variabila contor ca non-statica, atunci ea ar fi existat in atatea exemplare, cate obiecte s-ar fi creat si ar fi contorizat pentru fiecare obiect in parte numarul de apeluri ale metodei move

In legatura cu drepturile de acces la membrii statici ai unei clase, regulile sunt aceleasi ca si pentru membrii non-statici.

Dintre clasele predefinite ale mediului Java, un exemplu tipic de clasa in care majoritatea membrilor sunt statici este clasa Math din pachetul java.lang. Aceasta contine metodele necesare aplicatiilor stiintifico-ingineresti: functii transcendente, functii de rotunjire numerica, constantele pi si e (care sunt campuri statice ale clasei). Cu toate aceste metode putem lucra fara a crea instante ale clasei Math. 
De asemenea, obiectul out folosit in operatiile de afisare pe ecran este un membru static al clasei System
In fine, metoda main care apare in clasa radacina am vazut inca de la inceput ca este o metoda statica. Ea este apelata inainte ca in program sa se creeze vreun obiect. 

Alte informatii

Tema

Rulati aplicatiile din modul. Vizitati resursele propuse la Alte informatii.

Observatii, comentarii sunt binevenite in Conferinta Software Consulting.

Se cere sa se defineasca o clasa Complex care sa modeleze lucrul cu numere complexe. Membrii acestei clase vor fi: 

  • 2 variabile de tip double pentru partile reala, respectiv imaginara ale numarului complex; 
  • un constructor cu 2 parametri de tip double pentru initializarea celor 2 variabile; 
  • un constructor cu un parametru de tip Complex
  • o metoda de calcul al modulului unui numar complex. Se precizeaza ca modulul unui numar complex este radicalul din (re*re + img*img), unde re este partea reala, iar img este partea imaginara. Pentru calculul radicalului se va folosi metoda predefinita Math.sqrt, care necesita un parametru de tip double si returneaza rezultat tot de tip double
  • o metoda de afisare pe ecran a valorii unui numar complex, sub forma: 

parte_reala + i*parte_imaginara

  • o metoda statica numita suma care sa accepte ca parametri 2 numere complexe si care sa returneze suma lor, sub forma de numar complex. 

Pe langa clasa Complex se va defini o clasa radacina ClientComplex care va contine exemple de utilizare a metodelor clasei Complex

Se cere sa se defineasca o clasa Data care sa modeleze data calendaristica. Membrii acestei clase vor fi: 

  • 3 variabile private de tip int pentru zi, luna, an; 
  • un constructor fara parametri, pentru initializarea variabilelor corespunzator datei implicite 1.1.2000;
  • un constructor cu 3 parametri de tip int pentru initializarea celor 3 variabile; 
  • un constructor cu un parametru de tip Data
  • 3 metode fara parametri getZi, getLuna, getAn, care returneaza valorile variabilelor clasei;
  • 3 metode setZi, setLuna, setAn, care primesc cate un parametru intreg si care modifica variabila la valoarea parametrului primit;
  • o metoda printData de afisare pe ecran a datei, sub forma: 

zi.luna.an

Pe langa clasa Data se va defini o clasa ClientData care va testa toate metode clasei Data

Observatie: Pentru ambele aplicatii, cele 2 clase pot fi definite in acelasi fisier .java, caz in care doar clasa client este publica sau in fisiere separate, cand ambele clase se declara publice.


Document Info


Accesari: 3756
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )