05.05.02.05_Tipurile Generice de Date, Reflexia Si Manipularea Evenimentelor

download 05.05.02.05_Tipurile Generice de Date, Reflexia Si Manipularea Evenimentelor

of 12

  • date post

    25-Nov-2015
  • Category

    Documents

  • view

    16
  • download

    3

Embed Size (px)

description

05.05.02.05_Tipurile Generice de Date, Reflexia Si Manipularea Evenimentelor

Transcript of 05.05.02.05_Tipurile Generice de Date, Reflexia Si Manipularea Evenimentelor

  • Tipurile generice de date, Reflexia si Manipularea evenimentelor

    Visul reprezint reflexia realitii n oglinda sufletului nostru. Mihaela Baci

    Obiective Manipularea si utilizarea tipurilor si claselor generice, manipularea arhitecturii claselor n timpul executrii programului (Reflexia) i manipularea evenimentelor.

    Cuprins 1.1. Tipurile generice de date 1.2. Reflexia 1.3. Manipularea evenimentelor

    1.1. Tipurile generice de date

    Manipularea tipurilor generice de date reprezint cel mai nalt grad de abstractizare i dinamic n crearea unei arhitecturi de clase a programului, arhitectur care s fie orientat pe obiect. Aceast descriere are la baz un concept simplu. Vom crea o clas, dar n ea nu vom evidenia explicit tipurile, ci doar vom manipula variabile, indiferent de tip. n acest mod, permitem utilizatorului clasei s-i aleag singur tipul cu care va manipula clasa. Aceasta influeneaz optimizarea clasei i ntreaga aplicaie.

    Iat un exemplu de ArrayList: ... ArrayList al = new ArrayList(); al.add("Petru"); ...

    Acest ArrayList conine un element de tip String. Dar, n cadrul clasei ArrayList acest obiect nu exist ca String, ci ca Object. Acest lucru nseamn c o anumit perioad de timp va fi consumat pentru transformarea String-ului introdus n obiect n timpul introducerii i retransformrii obiectului n String, n timpul extragerii datelor din list.

    n plus, odat cu extragerea datelor din list, nu este posibil s tratm obiectul direct ca pe un tip surs, ci trebuie s-l convertim explicit din obiect.

    Acest exemplu nu va funciona: Acest exemplu va funciona:

    ArrayList al = new ArrayList(); al.add("Petru"); String dinLista = al.get(0); ...

    ArrayList al = new ArrayList(); al.add("Petru"); String dinLista = (String)al.get(0); System.out.println(dinLista);

    Observm c singura diferen ntre aceste exemple este faptul c n al doilea exemplu exist conversiunea explicit n String. O astfel de abordare nu este de dorit din dou motive. n primul rnd, este necesar ca de fiecare dat s se efectueze conversiunea n tipul dorit, iar n al doilea rnd, pot aprea erori i n tipuri.

    Urmtorul exemplu va cauza o eroare n execuie, dei va fi tradus cu regularitate, deoarece, pur i simplu nu poate converti String-ul care nu conine numere n Integer:

    ArrayList al = new ArrayList(); al.add(1); al.add("Petru"); Integer dinLista = (Integer)al.get(1); System.out.println(dinLista);

  • 1.1.1. Utilizarea tipurilor generice. n locul abordrii mai sus menionate am putut s crem un ArrayList generic. Spre deosebire de un ArrayList obinuit, aceast clas accept i tipul obiectului pe care dorim s-l manipulm n ea. Datorit acestui fapt, se exclude posibilitatea de eroare n timpul manipulrii tipului din list, precum i conversiunea lui explicit. Iat cum ar arta exemplul cu lista generic de valori ntregi:

    ArrayList al = new ArrayList(); al.add(1); Integer dinLista = (Integer)al.get(0); System.out.println(dinLista);

    Dac ntr-o astfel de list am ncerca s introducem o valoare de alt tip (de exemlu al.add("Petru");), s-ar ajunge la o greeal n traducere. Acest lucru se va ntmpla deoarece am evideniat n mod explicit c tipul pe care dorim s manipulm n list este - Integer.

    Avnd n vedere faptul c listele generice cer un tip explicit de date, spre deosebire de manipularea listelor de obiecte, aceste liste cer i un tratament special al datelor introduse.

    n urmtorul exemplu exist dou clase: Persoana i Student. n timp ce, clasa Student motenete clasa Persoana:

    ... public class Persoana { public String nume; }

    ... public class Student extends Persoana { public String numarulCarnetuluiDeStudent; } ...

    Doarece ambele clase au numele de proprietate, poate c dorim s efectum o metod care va prezenta numele tuturor persoanelor din list. ns, aceast metod ar trebui s accepte ori tipul ArryList ori tipul ArryList (ori, bineneles, lista obiectelor, ceea ce nu este o opiune). Dac am ncerca s trecem lista studenilor pe lista Persoane sau invers, ar aprea o eroare n traducere. n loc de aceasta, putem accepta simbolul Wildcard (?) care simbolizeaz cea mai veche clas printe, sau mai exact, orice clas. Acest exemplu raporteaz o eroare:

    static void afisari(ArrayList os) { for(Persoana o : os) System.out.println(o.nume); } public static void main(String[] args) {

    ArrayList listaStudenti = new

    ArrayList(); ArrayList listaPersoane = new

    ArrayList(); Persoana o = new Persoana(); o.nume="Vasile"; Student s = new Student(); s.nume="Elena"; s.numarulCarnetuluiDeStudent="25/25"; listaPersoane.add(o); listaStudenti.add(s); afisari(listaStudenti); }

    Dar cu urmtoarea modificare, exemplul va fi complet funcional:

    static void afisari(ArrayList

  • for(Persoana o : os) System.out.println(o.nume); }

    Incercai s adugai linia; afisari(listaPersoane); Ce va afia? Este posibil s facem un pas nainte i s introducem o list de orice tip.

    static void afise(ArrayList os)

    { for(Object o : os) System.out.println(((Persoana)o).nume); }

    Esena utilizrii n acest mod a simbolului Wildcard (?) este evident dac se ia n considerare faptul c pentru acelai exemplu nu se poate ntrebuina tipul Object, ceea ce nseamn c acesta este unicul mod n care putem introduce dinamic o list generic n metod. Exemplu care nu funcioneaz:

    static void afisari(ArrayList os) { for(Object o : os) System.out.println(((Persoana)o).nume); }

    Motivul pentru care exemplul precedent nu funcioneaz este faptul c lista obiectelor (dei Object este n josul ierarhiei obiectelor) nu reprezint lista care este la sfritul ierarhiei listelor generice.

    1.1.2. Crearea claselor generice. Pn acum, am folosit clase care au posibilitatea acceptrii generice a tipurilor. S mai lum cteva exemple:

    LinkedList ll = new LinkedList(); ll.add("membrul meu al listei");

    Hashtable ht = new Hashtable(); ht.put("Stringul meu", 25);

    HashMap hm = new HashMap(); hm.put(15, 33);

    System.out.println(ll.get(0)); System.out.println(ht.get("Stringul meu")); System.out.println(hm.get(15));

    In urma executiei aobinem:

  • Pentru a ne crea propria clas generic, este necesar s evidenim acest lucru n definiia clasei:

    public class MyClass { public T t;

    }

    La crearea unei astfel de clase, Java trateaz automat fiecare tip definit drept generic (n acest caz este tipul T) ca Object. Astfel, dac iniiem aceast clas n felul urmtor:

    MyClass mk = new MyClass();

    vom avea proprietatea t, care va fi de tip Object:

    Pentru ca clasa s fie strict tipizat, la iniierea ei trebuie adugat i tipul dorit:

    MyClass mk = new MyClass();

    Acum clasa va fi tipizat i nu va putea s accepte niciun alt tip n afar de Integer.

    n acelai mod, putem aduga clasei i alte tipuri generice:

    public class MyClass {

    public T t; public T1 t1; public T2 t2; public MyClass(T t, T1 t1, T2 t2) { this.t = t; this.t1 = t1; this.t2 = t2; } } ...

    Apelarea clasei poate arta astfel: MyClass mk = new MyClass(35, "My text", true); System.out.println(mk.t+" "+mk.t1+" "+mk.t2);

    Sau astfel:

    MyClass mk = new MyClass(35, 15, 22); System.out.println(mk.t+mk.t1+mk.t2);

    Dou instane din exemplele de mai sus au tipuri de arhitectur total diferite. Dar, trebuie s inem minte c aceste instane rmn n continuare instanele acelorai clase, iar

  • compararea lor va da rezultatul corect n ciuda diferenei de tipuri: MyClass mk = new MyClass(35, 15, 22); MyClass mk1 = new MyClass(35, "", true); System.out.println(mk.getClass().equals(mk1.getClass()));

    Comparaia n ultima linie a codului d rezultatul true/adevrat. Bineneles, congruena n instane nu exist, astfel compararea lor va da rezultatul false/fals:

    System.out.println(mk.equals(mk1));

    Se pune ntrebarea: Ce se ntmpl dac dorim s ne asigurm c tipul pe care utilizatorul l va introduce va fi fr ndoial tipul adecvat? De exemplu, dorim ca o clas s execute operaiuni aritmetice, care evident nu se pot realiza cu tipuri non-numerice. Atunci trebuie s ne asigurm c tipul pe care utilizatorul l va introduce va fi limitat doar la tipuri numerice. n acest caz, putem limita tipul generic astfel nct el s devin subtipul unui anumit tip, prin cuvntul cheie extends:

    public class MyClass { public T t; public void showResult() { if(t.getClass().equals(Integer.class)) System.out.println(t.intValue()*t.intValue()); if(t.getClass().equals(Double.class)) System.out.println(t.doubleValue()*t.doubleValue()); } }

    Pentru o astfel de definiie a clasei, urmtoarele dou instanieri ar fi valide deoarece conin tipurile motenite din clasa Number:

    MyClass mk = new MyClass(); mk.t=15;

    MyClass mk1 = new MyClass(); mk1.t=15.0;

    mk1.showResult(); Raspuns: 255.0 (15.0*15.0)

    Urmtoarea instaniere NU ar fi valid, deoarece conine tipul String care nu

    motenete clasa Number: MyClass mk2 = new MyClass();

    1.2. Reflexia

    Reflexia este capacitatea limbajului de programare s manipuleze arhitectura

    claselor n timpul executrii programului. De obicei, acest lucru pare i sun cam complicat, dar de fapt, este vorba despre un concept foarte simplu. Aadar, cnd crem un program, manipulm clasele prin instanele sau elementele lor statice. Dar, de fapt, nou ne este pus la dispoziie doar acea parte a clasei care este menit utilizatorului. Structura lor, metodele, cmpurile i altele nu ne stau la dispoziie n sensul c nu putem privi corpul unei metode sau tipul unui cmp.

    S spunem c clasa MyClass are metoda: int add(int a,int