This shows you the differences between two versions of the page.
poo:breviare:breviar-03 [2018/09/22 08:49] mihai.nan |
poo:breviare:breviar-03 [2023/10/16 19:36] (current) carmen.odubasteanu [Laborator 3 - Clase și Obiecte în Java] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Laboratorul 3 ===== | + | ====== Breviar ====== |
- | * Responsabil laborator: Mihai Nan | + | ===== Laborator 3 - Clase și Obiecte în Java ===== |
- | * Profesor titular: Carmen Odubasteanu | + | ==== Introducere ==== |
+ | Presupunem că dorim //să descriem//, uzitând un limbaj de programare, un **obiect** carte. În general, o carte poate fi caracterizată prin titlu, autor și editură. Cum am putea realiza această descriere formală? | ||
- | ==== Clase si Obiecte in Java ==== | + | Dacă descriem acest obiect, tip abstract de date, într-un limbaj de programare structural, spre exemplu limbajul C, atunci vom crea, ca mai jos, o structură ''Carte'' împreună cu o serie de funcții cuplate de această structură. Cuplajul este realizat prin faptul că orice funcție care operează asupra unei cărți conține în lista sa de argumente o variabilă de tip ''Carte''. |
- | === 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. | + | <code c> |
- | + | ||
- | <code java> | + | |
typedef struct carte { | typedef struct carte { | ||
char *titlu, *autor; | char *titlu, *autor; | ||
Line 15: | Line 12: | ||
}*Carte; | }*Carte; | ||
- | void initializare(Carte this, char* titlu, char* autor, | + | void initializare(Carte this, char* titlu, char* autor, int nr_pagini) { |
- | int nr_pagini) { | + | |
this->titlu = strdup(titlu); | this->titlu = strdup(titlu); | ||
this->autor = strdup(autor); | this->autor = strdup(autor); | ||
Line 23: | Line 19: | ||
void afisare(Carte this) { | void afisare(Carte this) { | ||
- | printf("%s, %s - %d\n", this->autor, this->titlu, | + | printf("%s, %s - %d\n", this->autor, this->titlu, this->nr_pagini); |
- | this->nr_pagini); | + | |
} | } | ||
</code> | </code> | ||
- | Daca modelam acest obiect intr-un limbaj orientat pe obiecte (in acest caz, Java), atunci vom crea o **clasa** Carte ca mai jos. | + | Dacă modelăm acest obiect într-un limbaj orientat pe obiecte (în acest caz, Java), atunci vom crea o **clasă** ''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. | + | |
<code java> | <code java> | ||
Line 59: | Line 52: | ||
</code> | </code> | ||
- | === Clase si Obiecte === | + | <note tip>Se poate observa cu usurință, în cadrul exemplului de mai sus, că atât datele cât și **metodele** (funcțiile) care operează asupra acestora se găsesc în interiorul aceleiași entități, numită **clasa**. Evident, în codul din exemplu sunt folosite concepte care nu au fost încă explicate, dar cunoașterea și înțelegerea lor reprezintă scopul principal al acestui laborator.</note> |
- | == 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. | + | ==== Clase și Obiecte ==== |
- | * 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. | + | === Ce este un obiect? Ce este o clasă? === |
+ | |||
+ | * Atunci când un producător crează un produs, mai întâi acesta specifică toate caracteristicile produsului într-un document de specificații, iar pe baza acelui document se crează fizic produsul. De exemplu, calculatorul este un produs creat pe baza unui astfel de document de specificații. La fel stau lucrurile și într-un program orientat pe obiecte: mai întâi se crează **clasa** obiectului (documentul de specificații) care înglobează toate caracteristicile unui **obiect** (instanță a clasei), dupa care, pe baza acesteia, se crează (instanțiază) obiectul în memorie. | ||
+ | * În general, putem spune că o clasă furnizează un șablon ce spcifică datele și operațiile ce aparțin obiectelor create pe baza șablonului - în documentul de specificații pentru un calculator se menționează că acesta are un monitor și o serie de periferice. | ||
<note warning> | <note warning> | ||
- | 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. | + | **Programarea orientată pe obiecte** este o metodă de implementare a programelor în care acestea sunt organizate sub formă unor colecții de obiecte care cooperează între ele, fiecare obiect reprezentând instanța unei clase. |
</note> | </note> | ||
- | == Definirea 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. | + | * Din cele de mai sus deducem că o clasă descrie un obiect, în general, un nou tip de date. Într-o **clasă** găsim **date** și **metode** ce operează asupra datelor respective. |
- | * Pentru a defini o clasa, trebuie folosit cuvantul cheie **class** urmat de numele clasei. | + | * Pentru a defini o clasă, trebuie folosit cuvântul cheie ''class'' urmat de numele clasei. |
+ | |||
+ | <code java> | ||
+ | class <class_name> { | ||
+ | field; | ||
+ | method; | ||
+ | } | ||
+ | </code> | ||
<note warning> | <note warning> | ||
- | * O **metoda** nu poate fi definita in afara unei **clase**. | + | O **metodă** nu poate fi definită în 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. | + | Datele ''nume'', ''autor'', ''nr_pagini'' definite în clasa ''Carte'' se numesc **atribute**, **date-membru**, **variabile-membru** sau **câmpuri**, iar operațiile ''toString'' și ''main'' se numesc **metode**. |
+ | |||
+ | Fiecare clasă are un set de **constructori** care se ocupă cu **instanțierea** (inițializarea) obiectelor nou create. De exemplu, clasa ''Carte'' are doi constructori: unul cu trei parametri și unul fără parametri care îl apelează pe cel cu trei parametri. | ||
</note> | </note> | ||
- | == Crearea unui obiect == | + | === 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. | + | * Spuneam mai sus că un obiect reprezintă o instanță a unei clasa. În Java, instanțierea sau crearea unui obiect se face dinamic, folosind cuvântul cheie ''new'' și are ca efect crearea efectivă a obiectului cu alocarea spațiului de memorie corespunzător. |
- | * Asa cum fiecare calculator construit pe baza documentului de specificatii are propriile componente, fiecare obiect de tip **Calculator** are propriile sale atribute. | + | * Așa cum fiecare calculator construit pe baza documentului de specificații are propriile componente, fiecare obiect de tip ''Carte'' 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. | + | * **Inițializarea** se realizează prin intermediul constructorilor clasei respective. Inițializarea este, de fapt, parte integrantă a procesului de instanțiere, în sensul că imediat după alocarea memoriei ca efect al operatorului ''new'' este apelat constructorul specificat. Parantezele rotunde după numele clasei indică faptul că acolo este, de fapt, un apel la unul din constructorii clasei și 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. | + | * În Java, este posibilă și crearea unor **obiecte anonime**, care servesc doar pentru inițializarea altor obiecte, caz în care etapa de declarare a referinței obiectului nu mai este prezentă. |
<note warning> | <note warning> | ||
- | Declararea unui obiect nu implica alocarea de spatiu de memorie pentru acel obiect. Alocarea memoriei se face doar la apelul operatorului **new**. | + | Declararea unui obiect nu implică alocarea de spațiu de memorie pentru acel obiect. Alocarea memoriei se face doar la apelul operatorului ''new''. |
</note> | </note> | ||
Line 111: | Line 115: | ||
Point p; | Point p; | ||
Dimension d; | Dimension d; | ||
- | | + | |
public Rectangle(Point p, Dimension d) { | public Rectangle(Point p, Dimension d) { | ||
this.p = p; | this.p = p; | ||
Line 118: | Line 122: | ||
| | ||
public static void main(String args[]) { | public static void main(String args[]) { | ||
- | Rectangle patrat = new Rectangle(new Point(0, 0), | + | Rectangle patrat = new Rectangle(new Point(0, 0), new Dimension(10, 10)); |
- | new Dimension(10, 10)); | + | |
} | } | ||
} | } | ||
</code> | </code> | ||
- | === Referinte la obiecte === | + | === Referințe 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. | + | * În secțiunea anterioară, am văzut cum se definește o clasă și cum se crează un obiect. În această secțiune vom vedea cum putem executa operațiile furnizate de obiecte. Pentru a putea avea acces la operațiile furnizate de către un obiect, trebuie să deținem o **referință** 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. | + | * Odată un obiect creat, el poate fi folosit în următoarele sensuri: aflarea unor informații despre obiect, schimbarea stării sale sau executarea unor acțiuni. Aceste lucruri se realizează prin aflarea sau schimbarea valorilor variabilelor sale, respectiv prin apelarea metodelor sale. |
- | * Declarea unei referinte numite **carte** spre un obiect de tip {{font color|black|Carte}} se face in felul urmator: {{font color|blue|Carte carte;}} | + | * Declarea unei referințe numite ''carte'' spre un obiect de tip ''Carte'' se face în felul următor: ''Carte carte;'' |
<note warning> | <note warning> | ||
- | 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. | + | Faptul că avem la un moment dat o referință nu implică și existența unui obiect indicat de acea referință. Până în momentul în care referinței nu i se atașează un obiect, aceasta nu poate fi folosită. |
</note> | </note> | ||
<note important> | <note important> | ||
- | 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. | + | Valoarea ''null'', ce înseamnă **niciun obiect referit**, nu este atribuită automat tuturor variabilelor referința la declararea lor. Regula este următoarea: dacă referința este un membru al unei clase și ea nu este inițializată în niciun fel, la instanțierea unui obiect al clasei respective, referința va primi implicit valoarea ''null''. Dacă însă referința este o variabilă locală ce aparține unei metode, inițializarea implicită nu mai funcționeaza. De aceea, se recomandă ca programatorul să realizeze **intotdeauna** o inițializare explicită a obiectelor. |
</note> | </note> | ||
- | * 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. | + | * După cum am observat în exemplul oferit în prima secțiune, apelul metodei ''toString'' nu este ''toString(carte)'', ci ''carte.toString()'' întrucât metoda ''toString'' aparține obiectului referit de ''carte'' - se apelează metoda ''toString'' pentru obiectul referit de variabila ''carte''. |
- | * 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. | + | * Pentru o înțelegere mai bună a conceptului de referință a unui obiect, considerăm exemplul de mai jos în care creăm două obiecte de tip ''Carte'' precum și trei referințe 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. | + | * Fiecare dintre obiectele ''Carte'' are alocată o zonă proprie de memorie, în care sunt stocate valorile câmpurilor ''nume'', ''autor'', ''nr_pagini''. Ultima referință definită în exemplul de mai jos, ''c3'', va referi și ea exact același obiect ca ''c2'', adică al doilea obiect creat. |
<note imporntant> | <note imporntant> | ||
- | In cazul unui program, putem avea acces la serviciile puse la dispozitie de un obiect prin intermediul mai multor referinte. | + | În cazul unui program, putem avea acces la serviciile puse la dispoziție de un obiect prin intermediul mai multor referințe. |
</note> | </note> | ||
Line 159: | Line 162: | ||
</code> | </code> | ||
- | * 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. | + | * Atribuirea ''c3 = c2'' nu a făcut altceva decât să atașeze referinței ''c3'' obiectul având aceeași identitate precum cel referit de ''c2'', adică obiectul secund creat. |
+ | === Trimiterea datelor în Java === | ||
- | === Componenta unei clase === | + | Spre deosebire de C++, în Java nu există o modalitate prin care să poată fi făcută o diferențiere explicită între trimiterea parametrilor **<color red>prin referință</color>** și trimiterea acestora **<color blue>prin valoare</color>**. |
- | **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. | + | |
+ | Conform specificației Java ([[https://docs.oracle.com/javase/specs/jls/se9/html/jls-4.html#jls-4.3|secțiunea 4.3]]), transmiterea tuturor datelor, atât a celor de tip obiect, cât și a celor primitive, este definită următoarea regulă:. | ||
+ | |||
+ | <note important>In Java argumentele sunt trimise doar **<color blue>prin valoare</color>** (pass-by-value).</note> | ||
+ | |||
+ | Chiar dacă la o primă vedere această regulă poate să pară simplă, este necesară o explicație suplimentară. În cazul valorilor primitive, valoarea este considerată pur și simplu data asociată (exemple ''1'', ''10.5'', ''true'') iar valoarea parametrilor este copiată de fiecare dată când ei sunt plasați în apeluri. | ||
+ | |||
+ | În ceea ce privește obiectele, în Java, se utilizează următoarea regulă, mai extinsă: | ||
+ | |||
+ | <note important>Valoarea asociată unui obiecte este, de fapt, un pointer, numit referință, la obiectul din memorie.</note> | ||
+ | |||
+ | Spre exemplu, dacă definim o expresie de forma ''Foo foo = new Foo();'', variabila ''foo'' nu deține obiectul ''Foo'' creat, ci, mai degrabă, o valoare a pointerului pentru obiectul ''Foo'' creat. Valoarea acestui pointer la obiect (ceea ce în specificația Java se numește **o referință de obiect** sau pur și simplu **referință**) este copiată de fiecare dată când obiectul este plasat ca argument al unui apel. | ||
+ | |||
+ | În Java, numai următoarele operații pot fi efectuate pe o referință de obiect: | ||
+ | * accesarea câmurilor; | ||
+ | * invocarea metodelor; | ||
+ | * operatorul pentru castare; | ||
+ | * operatorul pentru concatenarea string-urilor (atunci când primește ca parametru o referință la un obiect, o să realizeze o conversie a referinței la String, prin invocarea metodei ''toString'' pentru obiectul referențiat); | ||
+ | * operatorul ''instanceof''; | ||
+ | * operatorii de egalitate pentru referințe: ''=='' și ''!=''; | ||
+ | * operatorul condițional: ''? :''. | ||
+ | |||
+ | <note tip>În practică, acest lucru înseamnă că putem schimba câmpurile obiectului trimis ca parametru într-o metodă și să invocăm metodele acestuia, însă nu putem schimba obiectul spre care pointează referința. Deoarece referința este plasată prin valoare, pointerul original este copiat în stiva de apeluri atunci când metoda este invocată.</note> | ||
+ | |||
+ | {{ :poo:breviare:java-pass-by-value.png |}} | ||
+ | |||
+ | Pentru a înțelege mai bine conceptele prezentate în această secțiune, puteți consulta și analiza rezultatele pentru următoarele secvențe de cod. | ||
+ | |||
+ | <code java> | ||
+ | int someValue = 10; | ||
+ | int anotherValue = someValue; | ||
+ | someValue = 17; | ||
+ | System.out.println("Some value = " + someValue); | ||
+ | System.out.println("Another value = " + anotherValue); | ||
+ | </code> | ||
+ | |||
+ | <code java> | ||
+ | public class Test { | ||
+ | public void process(int value) { | ||
+ | System.out.println("Entered method (value = " + value + ")"); | ||
+ | value = 50; | ||
+ | System.out.println("Changed value within method (value = " + value + ")"); | ||
+ | System.out.println("Leaving method (value = " + value + ")"); | ||
+ | } | ||
+ | |||
+ | public static void main(String args[]) { | ||
+ | Test processor = new Test(); | ||
+ | int someValue = 7; | ||
+ | System.out.println("Before calling method (value = " + someValue + ")"); | ||
+ | processor.process(someValue); | ||
+ | System.out.println("After calling method (value = " + someValue + ")"); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code java> | ||
+ | class Ball {} | ||
+ | |||
+ | class Main { | ||
+ | public static void main(String args[]) { | ||
+ | Ball someBall = new Ball(); | ||
+ | System.out.println("Some ball before creating another ball = " + someBall); | ||
+ | Ball anotherBall = someBall; | ||
+ | someBall = new Ball(); | ||
+ | System.out.println("Some ball = " + someBall); | ||
+ | System.out.println("Another ball = " + anotherBall); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code java> | ||
+ | class Vehicle { | ||
+ | private String name; | ||
+ | public Vehicle(String name) { | ||
+ | this.name = name; | ||
+ | } | ||
+ | public void setName(String name) { | ||
+ | this.name = name; | ||
+ | } | ||
+ | public String getName() { | ||
+ | return name; | ||
+ | } | ||
+ | @Override | ||
+ | public String toString() { | ||
+ | return "Vehicle[name = " + name + "]"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class VehicleProcessor { | ||
+ | public void process(Vehicle vehicle) { | ||
+ | System.out.println("Entered method (vehicle = " + vehicle + ")"); | ||
+ | vehicle.setName("A changed name"); | ||
+ | System.out.println("Changed vehicle within method (vehicle = " + vehicle + ")"); | ||
+ | System.out.println("Leaving method (vehicle = " + vehicle + ")"); | ||
+ | } | ||
+ | public void processWithReferenceChange(Vehicle vehicle) { | ||
+ | System.out.println("Entered method (vehicle = " + vehicle + ")"); | ||
+ | vehicle = new Vehicle("A new name"); | ||
+ | System.out.println("New vehicle within method (vehicle = " + vehicle + ")"); | ||
+ | System.out.println("Leaving method (vehicle = " + vehicle + ")"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class Main { | ||
+ | public static void main(String args[]) { | ||
+ | VehicleProcessor processor = new VehicleProcessor(); | ||
+ | Vehicle vehicle = new Vehicle("Some name"); | ||
+ | System.out.println("Before calling method (vehicle = " + vehicle + ")"); | ||
+ | processor.process(vehicle); | ||
+ | System.out.println("After calling method (vehicle = " + vehicle + ")"); | ||
+ | processor.processWithReferenceChange(vehicle); | ||
+ | System.out.println("After calling reference-change method (vehicle = " + vehicle + ")"); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === Componența unei clase === | ||
+ | **Clasele**, așa cum am văzut deja, sunt definite folosind cuvântul cheie ''class''. În următoarele secțiuni, vom vorbi despre diferite categorii de membri care pot apărea în interiorul unei clase. | ||
== Constructori == | == Constructori == | ||
- | * In multe cazuri, atunci cand instantiem un obiect, ar fi folositor ca obiectul sa aiba anumite atribute initializate. | + | * În multe cazuri, atunci când instanțiem un obiect, ar fi folositor ca obiectul să aibă anumite atribute inițializate. |
- | * Initializarea atributelor unui obiect se poate face in mod automat, la crearea obiectului, prin intermediul unui **constructor**. Principalele caracteristici ale unui constructor sunt: | + | * Inițializarea atributelor unui obiect se poate face în 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 are același nume ca clasa în care este declarat; |
- un constructor nu are tip returnat; | - un constructor nu are tip returnat; | ||
- | - un constructor se apeleaza automat la crearea unui obiect; | + | - un constructor se apelează automat la crearea unui obiect; |
- | - un constructor se executa la crearea obiectului si numai atunci. | + | - un constructor se execută la crearea obiectului și numai atunci. |
<note warning> | <note warning> | ||
- | 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. | + | Dacă programatorul nu prevede într-o clasa niciun constructor, atunci compilatorul va genera pentru clasa respectivă un constructor implicit fără niciun argument și al cărui corp de instrucțiuni este vid. |
</note> | </note> | ||
+ | |||
+ | {{ :poo:breviare:default-constructor1.png |}} | ||
<note warning> | <note warning> | ||
- | Daca programatorul include intr-o clasa cel putin un constructor, compilatorul nu va mai genera constructorul implicit. | + | Dacă programatorul include într-o clasă cel puțin un constructor, compilatorul nu va mai genera constructorul implicit. |
</note> | </note> | ||
+ | |||
+ | <code java> | ||
+ | class Carte { | ||
+ | private String autor, nume; | ||
+ | |||
+ | public Carte(String autor, String nume) { | ||
+ | this.autor = autor; | ||
+ | this.nume = nume; | ||
+ | } | ||
+ | |||
+ | public String toString() { | ||
+ | return "Autor: " + autor + "\n" + "Titlul: " + nume; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class Creion { | ||
+ | private String culoare; | ||
+ | |||
+ | public String getCuloare() { | ||
+ | return culoare; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class Test { | ||
+ | public static void main(String args[]) { | ||
+ | Carte c1, c2; | ||
+ | c1 = new Carte(); //EROARE, deoarece nu avem constructor de aritate 0 | ||
+ | c2 = new Carte("George Calinescu", "Enigma Otiliei"); //CORECT | ||
+ | Creion c3; | ||
+ | c3 = new Creion(); //CORECT, deoarece nu am definit niciun constructor => exista cel predefinit | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
== Membri statici == | == 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. | + | Atunci când definim o clasă, specificăm felul în care obiectele de tipul acelei clase arată și se comportă. Dar până la crearea efectivă a unui obiect, folosind ''new'', nu se alocă nicio zonă de memorie pentru atributele definite în cadrul clasei, iar la crearea unui obiect se alocă acestuia memoria necesară pentru fiecare atribut existent în clasa instanțiată. Tot până la crearea efectivă a unui obiect nu putem beneficia de serviciile definite în cadrul unei clase. Ei bine, există și o excepție de la regula prezentată anterior - **membrii statici** (atribute și metode) ai unei clase. Acești membri ai unei clase pot fi folosiți direct prin intermediul numelui clasei, fără a deține instanțe pentru respectiva clasă. |
<note warning> | <note warning> | ||
- | * Un membru static al unei clase caracterizeaza clasa in interiorul careia este definit precum si toate obiectele clasei respective. | + | Un membru static al unei clase caracterizează clasa în interiorul căreia este definit precum și 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. | + | Un membru al unei clase (atribut sau metodă) este static dacă el este precedat de cuvântul cheie ''static''. |
- | * 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. | + | |
+ | Din interiorul unei metode statice pot fi accesați doar alți membri statici ai clasei în care este definită metoda, accesarea membrilor nestatici ai clasei producând o eroare de compilare. | ||
+ | |||
+ | Trebuie avut în vedere contextul static al metodei **main**. Dintr-un context static nu se pot apela funcții nestatice, în schimb, se pot crea obiecte ale oricărei clase. | ||
</note> | </note> | ||
- | === Principii POO === | + | ==== Principii POO ==== |
<note important> | <note important> | ||
- | Mai multe functii pot avea acelasi nume in acelasi domeniu de definitie, daca se pot diferentia prin numarul sau tipul argumentelor de apel. | + | Mai multe funcții pot avea același nume în același domeniu de definiție, dacă se pot diferenția prin numărul sau tipul argumentelor de apel. |
</note> | </note> | ||
- | == Supraincarcarea == | + | === Supraîncarcarea === |
- | 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. | + | În Java, se pot găsi două sau mai multe metode, în cadrul aceleiași clase, care să aibă același nume, atâta timp cât argumentele lor sunt diferite. În acest caz, se spune că metoda este supraîncărcată, iar procedeul se numește **supraîncarcarea metodelor**. |
- | Pentru o mai buna intelegere a acestui principiu POO, se va oferi, in continuare, un exemplu pentru o metoda care determina maximul. | + | Pentru o mai bună înțelegere a acestui principiu POO, se va oferi, în continuare, un exemplu pentru o metodă care determină maximul. |
<code java> | <code java> | ||
Line 225: | Line 384: | ||
</code> | </code> | ||
- | Un alt exemplu elocvent, pentru acest prinicpiu POO, este operatorul "+" care executa operatii diferite in cotexte diferite. | + | Un alt exemplu elocvent, pentru acest prinicpiu POO, este operatorul ''+'' care execută operații diferite în cotexte diferite. |