This is an old revision of the document!


Laboratorul 3

* Responsabil laborator: Mihai Nan * Profesor titular: Carmen Odubasteanu

Clase si Obiecte in Java

Introducere

Presupunem ca dorim sa descriem, uzitand un limbaj de programare, un obiect carte. In general, o carte poate fi caracterizata prin titlu, autor si editura. Cum am putea realiza aceasta descriere formala?

Daca descriem acest obiect, tip abstract de date, intr-un limbaj de programare structural, spre exemplu limbajul C, atunci vom crea, ca mai jos, o structura Carte impreuna cu o serie de functii cuplate de aceasta structura. Cuplajul este realizat prin faptul ca orice functie care opereaza asupra unei carti contine in lista sa de parametri o variabila de tip Carte.

 typedef struct carte {
	char *titlu, *autor;
	int nr_pagini;
}*Carte;
 
void initializare(Carte this, char* titlu, char* autor, 
    int nr_pagini) {
	this->titlu = strdup(titlu);
	this->autor = strdup(autor);
	this->nr_pagini = nr_pagini;
}
 
void afisare(Carte this) {
	printf("%s, %s - %d\n", this->autor, this->titlu, 
	    this->nr_pagini);
}

Daca modelam acest obiect intr-un limbaj orientat pe obiecte (in acest caz, Java), atunci vom crea o clasa Carte ca mai jos.

Se poate observa cu usurinta, in cadrul exemplului de mai jos, ca atat datele cat si metodele (functiile) care opereaza asupra acestora se gasesc in interiorul aceleiasi entitati, numita clasa. Evident, in codul din exemplu sunt folosite concepte care nu au fost inca explicate, dar cunoasterea si intelegerea reprezinta scopul principal al acestui laborator.

class Carte {
    String nume, autor;
    int nr_pagini;
 
    public Carte(String nume, String autor, int nr_pagini) {
        this.nume = nume;
        this.autor = autor;
        this.nr_pagini = nr_pagini;
    }
 
    public Carte() {
        this("Enigma Otiliei", "George Calinescu", 423);
    }
 
    public String toString() {
        return this.autor + ", " + this.nume + " - " + this.nr_pagini;
    }
 
    public static void main(String args[]) {
        Carte carte;
        carte = new Carte("Poezii", "Mihai Eminescu", 256);
        System.out.println(carte);
    }
}

Clase si Obiecte

Ce este un obiect? Ce este o clasa?

* Atunci cand un producator creaza un produs, mai intai acesta specifica toate caracteristicile produsului intr-un document de specificatii, iar pe baza acelui document se creaza fizic produsul. De exemplu, calculatorul este un produs creat pe baza unui astfel de document de specificatii. La fel stau lucrurile si intr-un program orientat pe obiecte: mai intai se creaza clasa obiectului (documentul de specificatii) care inglobeaza toate caracteristicile unui obiect (instanta a clasei), dupa care, pe baza acesteia, se creaza (instantiaza) obiectul in memorie.

* In general, putem spune ca o clasa furnizeaza un sablon ce spcifica datele si operatiile ce apartin obiectelor create pe baza sablonului - in documentul de specificatii pentru un calculator se mentioneaza ca acesta are un monitor si o serie de periferice.

Programarea orientata pe obiecte este o metoda de implementare a programelor in care acestea sunt organizate ca si colectii de obiecte care coorpereaza intre ele, fiecare obiect reprezentand instanta unei clase.

Definirea unei clase

* Din cele de mai sus deducem ca o clasa descrie un obiect, in general, un nou tip de data. Intr-o clasa gasim date si metode ce opereaza asupra datelor respective.

* Pentru a defini o clasa, trebuie folosit cuvantul cheie class urmat de numele clasei.

* O metoda nu poate fi definita in afara unei clase.

* Datele “nume”, “autor”, “nr_pagini” definite in clasa Carte se numesc atribute, date-membru, variabile-membru sau campuri, iar operatiile toString si main se numesc metode.

* Fiecare clasa are un set de constructori care se ocupa cu instantierea (initializarea) obiectelor nou create. De exemplu, clasa Carte are doi constructori: unul cu trei parametri si unul fara parametri care il apeleaza pe cel cu trei parametri.

Crearea unui obiect

* Spuneam mai sus ca un obiect reprezinta o instanta a unei clasa. In Java, instantierea sau crearea unui obiect se face dinamic, folosind cuvantul cheie new si are ca efect crearea efectiva a obiectului cu alocarea spatiului de memorie corespunzator.

* Asa cum fiecare calculator construit pe baza documentului de specificatii are propriile componente, fiecare obiect de tip Calculator are propriile sale atribute.

* Initializarea se realizeaza prin intermediul constructorilor clasei respective. Initializarea este, de fapt, parte integranta a procesului de instantiere, in sensul ca imediat dupa alocarea memoriei ca efect al operatorului new este apelat constructorul specificat. Parantezele rotunde dupa numele clasei indica faptul ca acolo este de fapt un apel la unul din constructorii clasei si nu simpla specificare a numelui clasei.

* In Java, este posibila si crearea unor obiecte anonime, care servesc doar pentru initializarea altor obiecte, caz in care etapa de declarare a referintei obiectului nu mai este prezenta.

Declararea unui obiect nu implica alocarea de spatiu de memorie pentru acel obiect. Alocarea memoriei se face doar la apelul operatorului new.

class Point {
    int x, y;
 
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
 
class Dimension {
    int width, height;
 
    public Dimension(int width, int height) {
        this.width = width;
        this.height = height;
    }
}
 
class Rectangle {
    Point p;
    Dimension d;
 
    public Rectangle(Point p, Dimension d) {
        this.p = p;
        this.d = d;
    }
 
    public static void main(String args[]) {
        Rectangle patrat = new Rectangle(new Point(0, 0), 
            new Dimension(10, 10));
    }
}

Referinte la obiecte

* In sectiunea anterioara, am vazut cum se defineste o clasa si cum se creaza un obiect. In aceasta sectiune vom vedea cum putem executa operatiile furnizate de obiecte. Pentru a putea avea acces la operatiile furnizate de catre un obiect, trebuie sa detinem o referinta spre acel obiect. * Odata un obiect creat, el poate fi folosit in urmatoarele sensuri: aflarea unor informatii despre obiect, schimbarea starii sale sau executarea unor actiuni. Aceste lucruri se realizeaza prin aflarea sau schimbarea valorilor variabilelor sale, respectiv prin apelarea metodelor sale. * Declarea unei referinte numite carte spre un obiect de tip black|Carte se face in felul urmator: blue|Carte carte;

Faptul ca avem la un moment dat o referinta nu implica si existenta unui obiect indicat de acea referinta. Pana in momentul in care referintei nu i se ataseaza un obiect, aceasta nu poate fi folosita.

Valoarea null, ce inseamna niciun obiect referit, nu este atribuita automat tuturor variabilelor referinta la declararea lor. Regula este urmatoarea: daca referinta este un membru al unei clase si ea nu este initializata in niciun fel, la instantierea unui obiect al clasei respective referinta va primit implicit valoarea null. Daca insa referinta este o variabila locala ce apartine unei metode, initializarea implicita nu mai functioneaza. De aceea, se recomanda ca programatorul sa realizeze intotdeauna o initializare explicita a obiectelor.

* Dupa cum am observat in exemplul oferit in prima sectiune, apelul metodei toString nu este toString(carte), ci carte.toString() intrucat metoda toString apartine obiectului referit de carte - se apeleaza metoda toString pentru obiectul referit de variabila carte din fata lui. * Pentru o intelegere mai buna a conceptului de referinta a unui obiect, consideram exemplul de mai jos in care cream doua obiect de tip Carte precum si trei referinte spre acest tip de obiecte. * Fiecare dintre obiectele Carte are alocata o zona proprie de memorie, in care sunt stocate valorile campurilor “nume”, “autor”, “nr_pagini”. Ultima referinta definita in exemplul de mai jos, “c3”, va referi si ea exact acelasi obiect ca si “c2”, adica al doilea obiect creat.

In cazul unui program, putem avea acces la serviciile puse la dispozitie de un obiect prin intermediul mai multor referinte.

class Test {
    public static void main(String args[]) {
        Carte c1 = new Carte("Poezii", "Mihai Eminescu", 326);
        Carte c2 = new Carte("Camil Petrescu", "George Calinescu", 426);
        Carte c3 = c2;
        c3.autor = "George Calinescu";
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
    }
}

* Atribuirea “c3 = c2” nu a facut altceva decat sa ataseze referintei “c3” obiectul avand aceeasi identitate ca si cel referit de “c2”, adica obiectul secund creat.

Componenta unei clase

Clasele, asa cum am vazut deja, sunt definite folosind cuvantul cheie class. In urmatoarele sectiuni, vom vorbi despre diferite categorii de membri care pot apare in interiorul unei clase.

Constructori

* In multe cazuri, atunci cand instantiem un obiect, ar fi folositor ca obiectul sa aiba anumite atribute initializate. * Initializarea atributelor unui obiect se poate face in mod automat, la crearea obiectului, prin intermediul unui constructor. Principalele caracteristici ale unui constructor sunt: - un constructor are acelasi nume ca si clasa in care este declarat; - un constructor nu are tip returnat; - un constructor se apeleaza automat la crearea unui obiect; - un constructor se executa la crearea obiectului si numai atunci.

Daca programatorul nu prevede intr-o clasa niciun constructor, atunci compilatorul va genera pentru clasa respectiva un constructor implicit fara niciun argument si al carui corp de instructiuni este vid.

Daca programatorul include intr-o clasa cel putin un constructor, compilatorul nu va mai genera constructorul implicit.

Membri statici

Atunci cand definim o clasa, specificam felul in care obiectele de tipul acelei clase arata si se comporta. Dar pana la crearea efectiva a unui obiect folosind new nu se aloca nicio zona de memorie pentru atributele definite in cadrul clasei, iar la crearea unui obiect se aloca acestuia memoria necesara pentru fiecare atribut existent in clasa instantiata. Tot pana la crearea efectiva a unui obiect nu putem beneficia de serviciile definite in cadrul unei clase. Ei bine, exista si o exceptie de la regula prezentata anterior - membrii statici (atribute si metode) ai unei clase. Acesti membri ai unei clase pot fi folositi direct prin intermediul numelui clasei, fara a detine instante a respectivei clase.

* Un membru static al unei clase caracterizeaza clasa in interiorul careia este definit precum si toate obiectele clasei respective. * Un membru al unei clase (atribut sau metoda) este static daca el este precedat de cuvantul cheie static. Din interiorul unei metode statice pot fi accesati doar alti membri statici ai clasei in care este definita metoda, accesarea membrilor nestatici ai clasei producand o eroare de compilare. * Trebuie avut in vedere contextul static al metodei main. Dintr-un context static nu se pot apela functii nestatice, in schimb, se pot crea obiecte ale oricarei clase.

Principii POO

Mai multe functii pot avea acelasi nume in acelasi domeniu de definitie, daca se pot diferentia prin numarul sau tipul argumentelor de apel.

Supraincarcarea

In Java, se pot gasi doua sau mai multe metode, in cadrul aceleiasi clase, care sa aiba acelasi nume, atata timp cat parametrii lor sunt diferiti. In acest caz, se spune ca metoda este supraincarcata, iar procedeul se numeste supraincarcarea metodelor. Pentru o mai buna intelegere a acestui principiu POO, se va oferi, in continuare, un exemplu pentru o metoda care determina maximul.

class Test {
    public int maxim(int a, int b) {
        if(a > b)
            return a;
        else
            return b;
    }
 
    public int maxim(String s1, String s2) {
        if(s1.compareTo(s2) < 0)
            return 2;
        else
            return 1;
    }
 
    public int maxim(int a, int b, int c) {
        if(maxim(a, b) < c)
            return c;
        else
            return maxim(a, b);
    }
}

Un alt exemplu elocvent, pentru acest prinicpiu POO, este operatorul ”+” care executa operatii diferite in cotexte diferite.

poo/breviare/breviar-03.1537594564.txt.gz · Last modified: 2018/09/22 08:36 by mihai.nan
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0