Sunteți pe pagina 1din 18

Programarea Generică.

Metode generice. Clase generice


profesor Dobrovolischii Olga
Introducere în Programarea Generică

Analizăm următorul exemplu: Fie că avem o metodă care sortează valori de un anumit tip. Nu ne
vom referi la algoritmul de sortare utilizat . Vom atrage atenția la utilizarea algoritmului în situații
diferite.
De exemplu, o metodă care va sorta valori întregi: public class operatii{

public int []sort(int []array){
//algoritm de sortare
return array;
}
}

Peste un anumit timp dorim să sortăm valori de tip double sau String, ce vom face? Vom modifica
tipul de date cu care operează metoda? Sau vom scrie o altă metodă care de fapt are la bază același
algoritm?
Introducere în Programarea Generică

public class operatii{



public int []sort(int []array){
//algoritm de sortare
return array;
}
public double []sort(double []array){
//algoritm de sortare
return array;
}
public String[]sort(String []array){
//algoritm de sortare
return array;
}
}
Introducere în Programarea Generică

Aceste modalități nu sunt una din cea mai bună metodă de a scrie cod. Nu trebuie să modifici codul
de fiecare dată când apare o necesitate nouă. Scopul este , ca în asemenea cazuri , de scris o secvență
eficientă pe care mai apoi să o folosești cu succes în diferite contexte.

Dacă revenim la exemplul de mai sus, să fie așa o metodă de sortare care va putea fi utilizată atât
pentru sortarea valorilor reale cît și pentru sortarea valorilor întregi,etc nefiind necesar să îi modifici
tipul în tot codul.

Aceasta este permisă cu ajutorul programării generice care permite crearea unei porțiuni de cod
generalizat ce poate fi apelată pentru mai multe tipuri de date, și anume: clase generice, interfețe
generice, metode generice inclusiv constructori.
Metode Generice

Pentru definirea metodelor generice se respectă sintaxa:

[specificator_acces][static]<K,V> tip_returnat numeMetoda(generic_type


<K,V>p1,
generic_type<K,V>p2{
/*...*/)
}
Unde <K,V> sunt parametri de tip, cunoscuți și sub numele de variabile de tip, sunt identificatori care specifică un
nume de tip generic. Conform convenției pentru denumirea parametrilor de tip în Java pe care ar trebui să o
respectăm, acestea pot lua valorile:
● E pentru tipul unui element din listă, pentru clasele JCF
● K pentru parametrul cheie în lista Map, acronim de la Key
● V pentru parametru valoare în lista Map, acronim de la Value
● N pentru reprezentarea numerelor , acronim de la Number
● T pentru tip de date general, de obicei primul parametru
● S pentru tip de date general, de obicei al doilea parametru
● U pentru tip de date general, de obicei al treilea parametru
● V pentru tip de date general, de obicei al patrulea parametru
Exemplu Metodă Generică
Exemplu de calculare a numarului de apariții ale unui Exemplu de numărare a apariției unui elemnt într-un
caracter într-un String. tablou de orice tip.
public class Exemplu { public class Exemplu2 {
public static int numara(String[] vector, String item) {
int count = 0; public static <T> int numara(T[] vector, T item) {
for (String s : vector) int count = 0;
if (item.equals(s)) for (T i : vector)
if (item.equals(i))
count++;
return count; count++;
} return count;
}
public static void main(String[] args) {
String[] string = { "h", "e", "l", "l", "o", "w", "o", public static void main(String[] args) {
"r", "l", "d" }; String[] string = { "h", "e", "l", "l", "o", "w", "o",
System.out.println("Numarul de litere l:" + "r", "l", "d" };
numara(string, "l")); System.out.println("Numarul de litere l:" +
numara(string, "l"));
} Integer[] intregi = { 1, 0, 1, 1, 0, 0, 1, 1, 0, 1,
1, 0, 1, 0, 1 };
} System.out.println("Numarul de zerouri:" +
numara(intregi, 0));

}
Reguli cu privire la scrierea metodelor generice în Java

1. Toate declarațiile de metode generice au o secțiune delimitată prin paranteze unghiulare(<și >)
ce conține unul sau mai mulți parametri tip, separați prin virgulă ce sunt mereu plasați înainte
de tipul de return al metodei.
2. Corpul unei metode generice este declarat ca acela al oricărei alte metode. Rețineți că
parametrii de tip pot reprezenta doar tipuri de referință, nu și tipuri primitive(cum ar fi int,
double, char)
3. Putem folosi orice nume pentru parametrul tip . Cu toate acestea , T este o convenție în Java și
ar trebui să o urmăm
4. Metodele generice sunt extrem de generale și reutilizabile.
Clase generice

Java dispune de clase generice predefinite. Clasele ce fac parte din JCF toate sunt generice. Amintim
clasa ArrayList care are următoarea definiție:
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAcces,Cloneable,Serializable

<E> reprezintă parametru tip și permite listei să opereze cu orice tip de date. Astfel ați creat de
exemplu o listă de produse (ArrayList<Produs>), o listă de elevi(ArrayList<Elevi>) chiar și o listă
de valori întregi(ArrayList<Integer>). Ați operat de fapt cu aceeași clasă de creare a unei liste,
ArrayList, dar ați avut posibilitate să creați liste de diverse tipuri , chiar și clase definite proprii:
produse, elevi, angajat, etc.
Clase generice

Exemplu de clasă generică care construiește liste de valori întregi și șiruri de caractere.
import java.util.ArrayList;
Scopul programării generice import java.util.List;
este de a scrie o clasă,
public class Exemplu3 {
metodă, sau interfață pentru public static void main(String[] args) {
a o putea apela pentru List<Integer> intLista = new ArrayList<Integer>();
intLista.add(5);
diverse tipuri de date. intLista.add(7);
intLista.add(3);
intLista.add(2);
for (Integer i : intLista)
System.out.println(i + " ");
System.out.println();
List<String> strLista = new ArrayList<String>();
strLista.add("unu");
strLista.add("doi");
strLista.add("trei");
for (String i : strLista)
System.out.println(i + " ");
}
}
Exemplu
Fie că lucrăm cu baze de date ce gestionează resursele unei instituții. Am putea crea o clasă
StudentDAO desttinată special pentru transferul studenților în BD în felul următor:

La prima vedere totul este bine, vom adăuga și vom extrage un student din baza de date. Următoarea
etapă ar fi să adăugăm în BD profesorii, vom scrie la fel, un cod special și pentru asta, doar că într-o
clasă separată:
Exemplu
Pentru a evita dublarea codului și pentru a economisi timp e mai simplu de folosit în acest caz
programarea generică.
Cunoscînd facilitățile programării generice vom putea realiza o singură clasă:

Tipul parametrizat <T> al clasei semnifică orice tip, iar însăși clasa poartă denumirea de clasă generică
Exemplu
Vom folosi în felul următor această clasă:

Cu această clasă vom putea opera și cu alte resurse fără a defini o nouă clasă dar a utiliza clasa
generică și celelalte clase care am definit în acest proiect:
După cum ați văzut , putem scrie o clasă generică care funcționează cu diferite tipuri. Acest lucru
elimină redundanța și face codul mai lizibil,mai reutilizabil, și mai general. De asemenea, cînd se
adaugă un tip nou, clasa generică poate fi reutilizată fără a scrie cod suplimentar, economisind astfel
timpul dvs.

O clasă generică se crează respectînd sintaxa:

class name<T1,T2,...,Tn>{
/*...*/
}
public class Numar<T> { public class NumarInt {
private T valoare; private int valoare;

public void set(T valoare) { public void set(int valoare) {


this.valoare = valoare; this.valoare = valoare;
} }
public int get() {
public T get() { return valoare;
return valoare; }}
} class NumarDouble {
} private double valoare;

class Test_clasaGenerica { public void set(double valoare) {


public static void main(String[] args) { this.valoare = valoare;
Numar<Integer> intNum = new }
Numar<Integer>(); public double get() {
intNum.set(5); return valoare;
Numar<Double> doubleNum = new }}
Numar<Double>();
doubleNum.set(9.5); class Test_clasaGenerica {
System.out.println("Valoarea intreaga " + public static void main(String[] args) {
intNum.get()); NumarInt intNum = new NumarInt();
System.out.println("Valoarea reala " + intNum.set(5);
doubleNum.get()); NumarDouble doubleNum = new
NumarDouble();
} doubleNum.set(9.5);
System.out.println("Valoarea intreaga " +
} intNum.get());
System.out.println("Valoarea reala " +
doubleNum.get());}}
Reguli cu privire la scrierea claselor generice în Java

1. Parametrul tip poate fi utilizat ca tip efectiv în corpul clasei. După cum vedeți în clasa
GeneralADO, T este utilizat ca tip de parametru în metoda save() și ca tip returnare în metoda
get().
2. Parametrii de tip nu sunt adăugați niciodată după numele constructorilor sau metodelor. Sunt
utilizate doar după numele claselor și interfețelor.
3. Rețineți că dacă parametrul tip al unei metode generice nestatice este același ca și clasa de bază,
indicatorul <T> nu este necesar. Următoarea clasă ilustrează acest lucru:
Interfețe generice
interface numeInterfata<parametri_tip>{
Pentru a crea interfețe generice respectăm sintaxa: //…
}

interface calcule <T>{ class TestInterfataGenerica {


T aria(); public static void main(String args[]) {
} System.out.println("Aria
class Cerc implements calcule<Double> { cercului:");
int laturi[] = new int[1]; Cerc c1 = new Cerc(5);
System.out.printf("%10.2f",
Cerc(int x) { c1.aria());
this.laturi[0] = x;} System.out.println();
public Double aria() { System.out.println("Aria
return 2 * Math.PI * dreptunghiului:");
Math.pow(laturi[0], 2);}} Dreptunghi d1 = new
Dreptunghi(5, 2);
class Dreptunghi implements calcule<Integer> { System.out.println(d1.aria());
int laturi[] = new int[2]; }
Dreptunghi(int x, int y) {
this.laturi[0] = x; }
this.laturi[1] = y;}

public Integer aria() {


return laturi[0] * laturi[1];
}}
Sumar

1. Programarea generică este o extensie a programării orientate spre obiecte și definește un set de
reguli de definire și utilizare a tipurilor(clase, interfețe) și metodelor(metode, constructori)
generice.
2. Programarea generică înseamnă că aveți posibilitatea de a scrie o singură declarație de metodă
generică care poate fi apelată cu argumente de diferite tipuri. În baza tipurilor de argumente
transmise metodei generice, compilatorul gestionează în mod corespunzător fiecare apel la
metodă.
3. Deci genericitatea permite unui tip sau metode să opereze pe obiecte de diferite tipuri, oferind în
același timp siguranță la momentul compilării.
4. Programarea generică transferă erorile ce ar putea fi generate în momentul execuției la faza de
compilare, eliminînd la maxim excepția ClassCastException, asigurînd siguranța funcționării
aplicației.
Sumar