Sunteți pe pagina 1din 22

1

Prezentare 10:
Genericitate

PROGRAMARE ORIENTATA
OBIECT
2020
Polimorfism parametric

 Polimorfism parametric – posibilitatea de a scrie o functie


sau a un tip de date a.i. sa poata trata valori fara sa
depinda de informatii despre tipul lor
 O astfel de functie (tip de date) este numita functie

generica (tip de date generic)


 Introdus prima data in ML in 1976

 In prezent intalnit in mai multe limbaje (Haskell, Java, C#,


Scala, Python)
 Utilizat in colectii si in reflexie

20.11.2020 POO 2
Colectii Java < 1.5
 Initial, colectiile Java erau definite pentru valori de tip Object
 Puteau stoca valori de orice tip, toate tipurile fiind

subclase ale lui Object


 Dar trebuia folosita conversia explicita de tip pentru

extragerea elementelor, ceea conducea la erori

// Java 1.4:
ArrayList nume = new ArrayList();
nume.add(“Ana");
nume.add(“Maria");
String student = (String) nume.get(0);
// compileaza, dar genereaza eroare la executie
Patrat pt = (Patrat) nume.get(1);
20.11.2020 POO 3
Parametrizare de tip
List<Tip> nume = new ArrayList<Tip>(); sau
List<Tip> nume = new ArrayList<>();

 Din Java 1.5, la constructia unui obiect de tip


java.util.ArrayList, se specifica tipul elementelor continute, intre
< si >
 clasa ArrayList accepta un parametru de tip (este o clasa

generica)
List<String> nume = new ArrayList<String>();
nume.add(“Ana");
nume.add(“Maria");
String student = nume.get(0); // fara conversie
Patrat pt = (Patrat) nume.get(1); // eroare compilare

20.11.2020 POO 4
Parametrizare de tip
// o clasa parametrizata (generica)
public class ClasaGen<Tip> {
sau
public class ClasaGen<Tip, Tip, ..., Tip> {

 Folosind constructia <Tip>, cel care instantiaza clasa trebuie sa


foloseasca un parametru de tip
 Pot fi specificati mai multi parametri de tip, separati prin vigula

 Codul clasei se poate referi la acel parametru de tip prin nume


 Prin conventie se utilizeaza nume formate dintr-o litera:
T pentruTip, E pentru Element, N pentru Numar, K pentru Cheie, V pentru
Valoare

 Parametrul de tip este instantiat de client (E → String)


20.11.2020 POO 5
Parametrizare de tip si array

public class BArrs<T> {


private T oVal; // corect
private T[] unArray; // correct

public BArrs(T param) {


oVal = new T(); // eroare
Nu se pot crea obiecte sau
unArray = new T[10]; // eroare vectori avand ca tip un
} parametru de tip
}

20.11.2020 POO 6
Parametrizare de tip si array
public class GArrs<T> {
private T oVal; // ok
private T[] unArray; // ok

@SuppressWarnings("unchecked")
public GArrs(T param) {
oVal = param; // ok
unArray = (T[]) (new Object[10]); // ok
}
}

Se pot declara variabile avand ca tip un parametru de tip, trimite ca


parametru, folosi ca rezultat sau se pot crea vectori prin conversia Object[]
Conversia la un tip generic nu este type-safe a.i. va genera warning.

20.11.2020 POO 7
Egalitatea obiectelor generice

public class ArrayList<E> {


...
public int indexOf(E value) {
for (int i = 0; i < size; i++) {
// if (elementData[i] == value) {
if (elementData[i].equals(value)) { Se utilizeaza equals
return i; pentru a testa egalitatea
}
}
return -1;
}
}

20.11.2020 POO 8
O interfata generica
// Reprezinta o lista de valori
public interface List<E> {
public void add(E value);
public void add(int index, E value);
public E get(int index);
public int indexOf(E value);
public boolean isEmpty();
public void remove(int index);
public void set(int index, E value);
public int size();
}

public class ArrayList<E> implements List<E> { ...


public class LinkedList<E> implements List<E> { ...

20.11.2020 POO 9
Metode generice
public static <Tip> tipRezultat met(param) {
public class Exemplu {
...
public static <T> void afisArr(T[] unArr)
{
for (T a : unArr) {
System.out.print(a);
System.out.print(‘ ‘);
}
}
} Atunci cand exista o metoda generica intr-o clasa (de
cele mai multe ori statica), tipul rezultatului trebuie
precedat de parametrul de tip

20.11.2020 POO 10
Limitarea parametrilor de tip
<Tip extends SuperTip>
 O limita superioara; accepta supertipul specificat sau oricare dintre
subtipuri
 Pot fi specifiate mai multe interfete cu & :
<Tip extends ClassA & InterfaceB & InterfaceC & ...>

<Tip super SuperTip>


 O limita inferioara; accepta tipul specificat sau oricare dintre
supertipuri

20.11.2020 POO 11
Limitarea parametrilor de tip

public class Patrat<T> {


private T lat;
public Patrat(T ilat) {
lat = ilat;
}
public T getLat() {
return lat;
}

public double getArie() {


double s = lat.doubleValue(); //eroare compilare
return s*s;
}
}

20.11.2020 POO 12
Limitarea parametrilor de tip

public class Patrat<T extends Number> {


private T lat;
public Patrat(T ilat) {
lat = ilat;
}
public T getLat() {
return lat;
}

public double getArie() {


double s = lat.doubleValue(); //ok
return s*s;
}
}

20.11.2020 POO 13
Limitarea parametrilor de tip
Vrem sa scriem o metoda statica care determina valoarea minima
dintr-un vector (array)

public ClasaM {
public static <T> T arrMin(T[] unArr) {
T min = unArr[0]; T trebuie limitat ai sa
for (T a: unArr) { reprezinte tipurile care au
if (a.compareTo(min) < 0) metoda compareTo
min = a;
}
return min;
}
}

20.11.2020 POO 14
Limitarea parametrilor de tip
Vrem sa scriem o metoda statica care determina valoarea minima
dintr-un vector (array)

public ClasaM {
public static <T extends Comparable<T>> T arrMin(T[] unArr) {
T min = unArr[0];
for (T a: unArr) {
if (a.compareTo(min) < 0)
min = a;
}
return min;
}
}

20.11.2020 POO 15
Wildcards
? reprezinta un tip de date necunoscut

class Pereche<T> {…}



Pereche<?> oPer = new Pereche<>(“mar”, “portocala”);
Pereche<?> altaPer = new Pereche<>(1, 2);

public static void afisPereche(Pereche<?> per) [
System.out.println(per);
}

afisPereche(oPer); // ok
afisPereche(altaPer); // ok

20.11.2020 POO 16
Wildcards
? reprezinta un tip de date necunoscut

class Pereche<T> {…}



Pereche<?> oPer = new Pereche<>(“mar”, “portocala”);
Pereche<?> altaPer = new Pereche<>(1, 2);

public static void afisPereche(Pereche<Object> per) [
System.out.println(per);
}

afisPereche(oPer); // eroare compilare
afisPereche(altaPer); // eroare compilare

20.11.2020 POO 17
Limitarea wildcards
<<interface>>
Comparable<T>

+compareTo(ob: T): integer

Widget Consideram o ierarhie de


obiecte comparabile
+compareTo(ob: T): integer

Gadget

20.11.2020 POO 18
Limitarea wildcards
Vrem sa putem compara nu numai obiecte Gadget intre ele, dar si cu
obiecte Widget daca au aceeasi baza de comparatie

public ClasaM {
public static <T extends Comparable<? super T>> T arrMin(T[] unArr)
{
T min = unArr[0];
for (T a: unArr) { ? super T reprezinta orice
if (a.compareTo(min) < 0) superclasa a lui T
min = a;
}
return min;
}
}
20.11.2020 POO 19
Genericitate si subtipare
 Este List<String> un subtip al tipului List<Object>?
 Este Set<Cal> un subtip al tipului Collection<Animal>?

 Nu. Ar viola principiul Liskov Substitutability Principle


 Daca am putea trimite Set<Cal> unei metode care asteapta
Collection<Animal> acea metoda ar putea adauga si alte animale

Set<Cal> set1 = new HashSet<Cal>();


Set<Animal> set2 = set1; // ilegal
...
set2.add(new Magar());
Magar mg = set1.get(0); // eroare

20.11.2020 POO 20
Genericitate si conversie de tip
 Conversia catre tipuri generice va genera warning:
List<?> l = new ArrayList<String>(); // ok
List<String> ls = (List<String>) l; // warning

 Compilatorul va da un “unchecked warning”, pentru ca nu va fi verificat


de sistemul runtime
 Daca este necesara o astfel de conversie, ceva e gresit

 Acelasi lucru este adevarat pentru parametri de tip:


public static <T> T conv(T t, Object o) {
return (T) o; // unchecked warning
}

20.11.2020 POO 21
Type erasure
 Toate tipurile generice nelegate devin Object cand sunt compilate
 Motivatie: compatibilitate cu vechiul byte code.
 La executie, toate instantierile generice au acelasi tip

List<String> lst1 = new ArrayList<String>();


List<Integer> lst2 = new ArrayList<Integer>();
lst1.getClass() == lst2.getClass() // true

 Nu se poate utiliza instanceof pentru un parametru de tip


Collection<?> cs = new ArrayList<String>();
if (cs instanceof Collection<String>) {
// ilegal
}
20.11.2020 POO 22

S-ar putea să vă placă și