Clase şi obiecte

Obiectele sunt cheia înţelegerii tehnologiei orientate pe obiect. Priveşte în jurul tău observă câteva obiecte reale: laptopul, câinele, masa, televizorul, maşina etc.

Obiectele din lumea reală au 2 caracteristici: o stare şi un comportament. Câinii au o stare (nume, culoare, rasă, foame) şi un comportament (latră, aleargă, se învârt în jurul cozii). Maşinile au şi ele o stare (viteza curentă, culoare) şi un comportament (schimbă viteza, frâneaza). Identificarea stării şi comportamentului pentru obiectele din lumea reală este o modalitate bună de a începe să gândeşti în termeni de programare orientată pe obiect.

Stai un minut şi gândeşte-te la obiectele reale pe care le vezi în jurul tău. Pentru fiecare, pune-ţi 2 întrebări: "Ce stare poate avea obiectul?" şi "Ce acţiuni poate face obiectul?". Scrie observaţiile pe care le faci. Vei observa că fiecare obiect are o complexitate diferită. Becul e posibil să aibă doar 2 stări (aprins şi stins) şi 2 comportamente sau acţiuni (aprinde şi stinge). Dar radioul e posibil să conţina stări adiţionale (deschis, închis, volumul curent, staţia) şi comportamente (deschide, închide, dă mai tare, dă mai încet, schimbă staţia). Vei mai observa şi că unele obiecte pot conţine alte obiecte (ex: ceasul poate avea o baterie, maşina are un volan, etc). Aceste observaţii din lumea reală pot fi traduse în programarea orientată pe obiect.

Obiectele software sunt conceptual similare cu obiectele din realitate: şi ele au o stare şi un comportament. Un obiect îşi salvează starea în câmpuri (eng.: fields) (variabile din limbajele de programare) şi îşi expune comportamentul prin metode. Metodele operează cu starea internă a unui obiect şi sunt mecanismul principal pentru comunicarea între obiecte. În mod normal, schimbarea stării şi interacţiunea dintre obiecte se face doar prin metode.

Să luăm de exemplu o bicicletă. După atribuirea unei stări (viteza curentă, culoare), prin furnizarea metodelor care schimbă starea respectivă, obiectul rămâne în control pentru modul în care este folosit din afara acestuia. De exemplu, dacă bicicleta poate merge cu o viteză maximă de 100 km/h, o metodă care să îi schimbe viteza ar putea refuza orice valoare mai mică ca 0 şi mai mare ca 100.

Prin gruparea codului în obiecte software individuale avem o serie de beneficii, printre care:

  1. Modularitate: codul sursă al unui obiect poate fi scris şi menţinut independent de codul sursă al altor obiecte. O dată creat, un obiect poate fi uşor pasat prin sistem.
  2. Ascunderea informaţiilor: atât timp cât interacţiunea se face doar cu metodele obiectelor, detaliile de interne de implementare rămân ascunse de lumea externă.
  3. Reutilizare: dacă un obiect există deja (poate a fost scris de un alt developer), poţi folosi obiectul respectiv în program. Această tehnică permite specialiştilor să implementeze şi să testeze task-uri complexe, specifice obiectelor, despre care poţi să ai încredere că vor funcţiona în propriul cod.
  4. Uşurinţa de schimbare: dacă un anume obiect devine problematic, poţi să îl ştergi din aplicaţie şi să îl înlocuieşti cu alt obiect. Acest lucru este analog cu repararea problemelor din lumea reală. Dacă se consumă bateria de la ceas, înlocuim bateria, nu tot ceasul.

Clase

În lumea înconjurătoare o să găseşti adesea multe obiecte de acelaşi tip. Este posibil să existe 1000 de biciclete, toate cu aceeaşi marcă şi aceeaşi culoare. Fiecare bicicletă a fost construită cu aceleaşi instrucţiuni (acelaşi blueprint, sau "matriță"), deci conţine aceleaşi componente. În termeni orientaţi pe obiecte, putem spune că bicicletaTa ta este o instanţă (un singur exemplar) a clasei de obiecte cunoscute ca Bicicletă. O clasă este o matriță din care sunt create obiecte individuale.

Următoarea clasă este o implementare posibilă a clasei Bicicletă.

public class Bicicleta {

    // atribute (stari)
    int anFabricatie;
    String culoare;
    
    // metode (comportamente)
    void vopseste(String nouaCuloare) {
        culoare = nouaCuloare;
    }
    
    void afiseazaStarea() {
        System.out.println("Anul fabricatiei: " + anFabricatie
                + " culoarea: " + culoare);
    }
    
}

Clasa de mai sus poate fi pusă într-un nou fişier Java (din Eclipse, când îţi creezi o nouă clasă). Câmpurile anFabricatie şi culoare reprezintă starea obiectului, iar metodele (vopseste() şi afiseazaStarea() ) definesc modul în care acesta interacţionează cu lumea din afară.

Poate ai observat că mai sus în clasa de mai sus nu avem metoda main. Acest lucru se întâmplă din cauza faptului că nu este o aplicaţie completă. Este doar blueprint-ul pentru bicicletele care vor fi folosite ulterior într-o aplicaţie. Responsabilitatea pentru a crea noi biciclete îi revine unei alte clase din aplicaţie.

Exemplul de mai jos creează 2 biciclete. În exemplu se interacţionează atât cu câmpurile cât şi cu metodele clasei. Pentru a interacţiona (sau apela) câmpurile acestora, se va folosi denumirea obiectului urmată de punct (.).

class BicicletePeDealVara {
    public static void main(String[] args) {

        // creearea obiectelor
        Bicicleta bicicleta1 = new Bicicleta();    // o instanță a clasei Bicicleta 
        Bicicleta altaBicicleta = new Bicicleta(); // o alta instanță a clasei Bicicleta

        // folosirea câmpurilor asemenea unor variabile
        bicicleta1.anFabricatie = 2000;
        bicicleta1.culoare = "Rosu";
        System.out.println("Prima bicicleta a fost fabricata in "
                 + bicicleta1.anFabricatie + " si vopsita cu " + bicicleta1.culoare);
        
        // metodele sunt apelate la fel ca şi câmpurile
        bicicleta1.vopseste("Verde");
        bicicleta1.afiseazaStarea();
        
        altaBicicleta.vopseste("Albastru");
        altaBicicleta.anFabricatie = 2008;
        altaBicicleta.afiseazaStarea();
    }
}

Implicit, câmpurile unei clase au valori predefinite. Acestea sunt 0 pentru numere, false pentru booleene şi null pentru obiecte. Dacă nu dăm o valoare câmpurilor atunci când le declarăm, acestea îşi vor lua automat valorile implicite.

Exerciţii

1. Pentru fiecare obiect pe care îl observi în jurul tău crează câte o nouă clasă. Crează apoi 2 obiecte pentru fiecare clasă.

Soluţie Orientativă

Soluţie Orientativă

public class Laptop {
    String marca;
    double procesor;
    int ram;
    
    void initializareStare(String nouaMarca, double noulProcesor, int noulRam) {
        marca = nouaMarca;
        procesor = noulProcesor;
        ram = noulRam;
    }
    
    void afisareStare() {
        System.out.println("Laptopul este facut de " + marca
                + " si are specificatiile:\n"
                + ram + " GB ram\n"
                + procesor + "GHz cpu");
    }
}

public class Testare {
    public static void main(String[] args) {
        Laptop lap = new Laptop();
        lap.initializareStare("Dell", 2.8, 4);
        lap.afisareStare();
        
        Laptop altLaptop = new Laptop();
        altLaptop.initializareStare("Asus", 1.9, 8);
        altLaptop.afisareStare();
    }
}


2. Să se creeze clasa Adresa. Aceasta ar trebui să conţină cel puţin câmpurile strada, numar şi oras. Să se întrebe utilizatorul la ce adresă locuieşte, să se reţină valorile introduse într-un obiect de tipul Adresa şi să se afişeze, folosind o metodă din acesta.

Soluţie

Soluţie

public class Adresa {
    String strada;
    String numar;
    String oras;
    
    void citesteAdresa() {
        Scanner sc = new Scanner(System.in);
        System.out.println("In ce oras locuiesti?");
        oras = sc.next();
        System.out.println("Pe ce strada?");
        strada = sc.next();
        System.out.println("La ce numar?");
        numar = sc.next();
    }
}

public class Testare {
    public static void main(String[] args) {
        Adresa adr = new Adresa();
        adr.citesteAdresa();
        System.out.println(adr.strada + " " + adr.numar + " " + adr.oras);
    }
}


3. Să se creeze clasa Student ce conţine câmpurile nume, prenume şi nota. Să se citească informaţii despre un student, să se reţină într-un obiect al clasei Student şi să se afişeze folosind o metodă.

4. La fel ca mai sus, să se creeze clasa Caine cu câmpurile rasa, nume, varsta, culoare, talie. Să se citească, să se reţină în obiecte şi să se afişeze informaţii despre 2 căţei.

Resurse

Discussion

, 2016/04/01 13:14

Am clasa Adresa, in care constructorul imi ia input pentru: Strada (string), Numar (int) si Oras (String). Cand rulez si apelez constructorul ca sa instantiez obiectul (in alta clasa care are metoda main), imi spune terminated inainte sa mai bag si string-ul Oras, fara sa logheze nici o eroare si fara sa imi sara debugger-ul.

Cod-ul arata asa:


package obiecte;

import java.util.Scanner;

public class Adresa {

public String strada;
public int numar;
public String oras;

Scanner scan = new Scanner(System.in);
public Adresa(){
	
	System.out.println("Input street");
	this.strada = scan.nextLine();
	
	System.out.println("Input street number");
	this.numar = scan.nextInt();	
	
	System.out.println("Input City");
	this.oras = scan.nextLine();
	
}

}


Apelez constructorul din main cu codul:


	Adresa adresa = new Adresa();	
	
	System.out.println(adresa.oras);

—-

In momentul in care imi printeaza "Input City" apare Terminated si nu mai apuca sa ruleze si celelalte instructiuni. Din investigatiile mele, daca cer al 2lea string (Oras) inainte de int (numar), merge fara probleme. De asemenea, daca las structura asa dar int-ul (numar) il iau ca string si il parsez in int, la fel, functioneaza.

Nu inteleg care este efectiv problema.

Multumesc, Adrian

, 2016/04/01 16:03

Este o problema care apare cand folosesti nextLine() dupa metode care cer altfel de input, cum ar fi, in cazul tau, nextInt() - acestea nu proceseaza si caracterul care marcheaza sfarsitul liniei (cand apesi Enter), astfel incat toata informatia va fi preluata si de metoda nextLine() care urmeaza.

Solutia cea mai buna ar fi sa folosesti un nextLine() gol imediat dupa nextInt(), sau sa folosesti doar next() pentru a cere orasul, in loc de nextLine():

System.out.println("Input street number");
this.numar = scan.nextInt();
scan.nextLine();
System.out.println("Input street number");
this.numar = scan.nextInt();
 
System.out.println("Input City");
this.oras = scan.next();
, 2016/03/13 17:10

Buna,

Solutia oferita la ex 1 are o mica eroare, "ram" ar fi trebuit setat double nu int sau initializate altfel.

, 2016/03/13 19:12

Bună observaţie, aşa este. Ultimii doi parametri pasaţi la crearea obiectelor au ordinea inversată - în loc de "Dell", 4, 2.8 trebuia "Dell", 2.8, 4. La fel şi pentru al doilea obiect. Am modificat soluţia.

, 2016/01/28 14:23

Buna ziua,

nu inteleg de ce atat la exercitiu 2 cat si la 3 nu-mi retine valorile introduse. Mai jos este Consola din exercitiu nr 3

"Introdu numele Romeo Introdu prenumele Diego Introdu ultima nota de promovare 9,4 Numele este null, prenumele este null, nota finala este: 0.0"

codul pentru clasa Student este: import java.util.Scanner;

public class Student {

String nume;
String prenume;
double nota;

void infoStudent(){
	Scanner sc= new Scanner(System.in);
	System.out.println("Introdu numele");
	String nume= sc.nextLine();
	System.out.println("Introdu prenumele");
	String prenume= sc.nextLine();
	System.out.println("Introdu nota de promovare");
	double nota= sc.nextDouble();
	
}

} si cel folosit ca sa "testez":

public class InformazioniStudente {

public static void main(String[] args) {
	Student std = new Student();
	std.infoStudent();
	System.out.println("Numele este "+std.nume+", prenumele este "+std.prenume+ ", nota finala este: "+std.nota);
	
}

}

Multumesc

, 2016/01/29 16:14

Trebuie sa folosesti variabilele declarate la inceputul clasei Student (nume, prenume si nota), nu sa declari altele noi:

Scanner sc= new Scanner(System.in);
System.out.println("Introdu numele");
String nume= sc.nextLine();
System.out.println("Introdu prenumele");
String prenume= sc.nextLine();
System.out.println("Introdu nota de promovare");
double nota= sc.nextDouble();

Codul corect pentru clasa Student ar fi urmatorul:

import java.util.Scanner;
 
public class Student {
 
	String nume;
	String prenume;
	double nota;
 
	void infoStudent(){
		Scanner sc= new Scanner(System.in);
		System.out.println("Introdu numele");
		nume= sc.nextLine();
		System.out.println("Introdu prenumele");
		prenume= sc.nextLine();
		System.out.println("Introdu nota de promovare");
		nota= sc.nextDouble();
	}
}
You could leave a comment if you were logged in.