Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-ca-cd:laboratoare:clase-interne [2024/11/10 16:36]
silvia_elena.nistor [Laboratorul 6: Visitor Pattern]
poo-ca-cd:laboratoare:clase-interne [2024/12/15 14:12] (current)
maria.enescu [Exerciții]
Line 1: Line 1:
-===== Laboratorul ​6Visitor pattern ===== +===== Laboratorul ​10Clase interneLambda expresii. =====
- +
-**Video introductiv:​** [[https://​www.youtube.com/watch?v=_mfLYYInv6c| link ]] +
- +
-==== Obiective ==== +
- +
-  * Prezentarea design pattern-ului Visitor și familiarizarea cu situațiile în care acesta este util de aplicat +
- +
-==== Visitor Design Pattern ==== +
- +
-<​note>​Design pattern-urile reprezintă soluții generale și reutilizabile ale unei probleme comune în design-ul software. Un design pattern este o descriere a soluției sau un template ce poate fi aplicat pentru rezolvarea problemei, nu o bucata de cod ce poate fi aplicata direct. În general pattern-urile orientate pe obiect arată relațiile și interacțiunile dintre clase sau obiecte, fără a specifica însă forma finală a claselor sau a obiectelor implicate.</​note>​  +
- +
-//Visitor// este un **behavioral design pattern** ce oferă posibilitatea de a adăuga în mod __extern__ funcționalități pe o întreagă ierarhie de clase fără să fie nevoie să modificăm efectiv structura acestora.  +
- +
-Acest pattern este behavioral (//​comportamental//​) pentru că definește modalități de comunicare între obiecte.  +
- +
-=== Aplicabilitate === +
- +
-Pattern-ul **Visitor** este util când: +
-  * se doreşte prelucrarea unei //structuri complexe//, ce cuprinde mai multe obiecte de //tipuri diferite//​ +
-  * se dorește definirea de operații specifice pentru aceeași structură, fără a polua interfeţele claselor implicate, cu multe detalii specifice algoritmilor. Vizitatorul centralizează logica comună, păstrând în același timp detaliile specifice în interiorul acestuia. +
-  * ** clasele ce se doresc prelucrate se modifică rar, în timp ce operaţiile de prelucrare se definesc des**. Vizitatorul permite adăugarea de noi funcționalități fără modificarea claselor existente. +
- +
-=== Structură ===  +
- +
-{{ .:​visitor:​visitor.png?​680 | Componente pattern Visitor }} +
- +
-Structura design pattern-ului "​Visitor"​ este formată din următoarele componente:​ +
- +
-**Client:​** +
-   * Este clasa consumatoare a design pattern-ului "​Visitor"​. +
-   * Are acces la obiectele din structura de date și poate instrui aceste obiecte să accepte un "​Visitor"​ pentru a realiza prelucrările corespunzătoare. +
-   * Exemplu: O aplicație care procesează diferite tipuri de elemente într-o structură de date complexă. +
- +
-**Visitor:​** +
-   * Este o interfață sau o clasă abstractă folosită pentru a declara operațiile de vizitare pentru toate tipurile de clase vizitabile. +
-   * Conține metode de vizitare corespunzătoare fiecărui tip de clasă vizitabilă. +
-   * Exemplu: Interfața Visitor cu metodele visit(ElementA elementA), visit(ElementB elementB), etc. +
- +
-**ConcreteVisitor:​** +
-   * Pentru fiecare tip de "​Visitor",​ toate metodele de vizitare definite în "​Visitor"​ trebuie implementate. +
-   * Fiecare "​Visitor"​ este responsabil pentru diferite operații. +
-   * Exemplu: Clasa ConcreteVisitorA implementând interfața Visitor cu metodele sale specifice pentru tratarea diferitelor tipuri de elemente. +
- +
-**Visitable:​** +
-   * Este o interfață pentru obiecte pe care pot fi aplicate operațiile +
-   * Această operație permite unui obiect să fie "​vizitat"​ de către un obiect "​Visitor"​. +
-   * Exemplu: Interfața Visitable cu metoda accept(Visitor visitor). +
- +
-**ConcreteVisitable:​** +
-   * Aceste clase implementează interfața Visitable sau clasa și definesc operația accept. +
-   * Prin intermediul acestei operații, obiectul "​Vizitabil"​ primește un obiect "​Visitor"​. +
-   * Exemplu: Clasele ConcreteElementA,​ ConcreteElementB,​ etc., care implementează interfața Visitable și definesc metoda accept. +
- +
- +
-<note tip> Flowul aplicării acestui pattern: +
-  -  Când un client dorește să efectueze operații pe obiectele vizitabile, el creează un obiect vizitator corespunzător,​ le "​vizitează"​ apelând metoda accept, iar fiecare obiect vizitabil interacționează cu vizitatorul prin intermediul metodelor visit. +
-  -  Acest pattern oferă o modalitate de a separa algoritmii de obiectele pe care operează, facilitând extinderea și adăugarea de noi operații fără a modifica clasele obiectelor vizitabile. +
-</​note>​ +
- +
-<note important>​ +
- +
-**Visitor și structurile de date** +
- +
-Aparent, folosirea lui //accept// este artificială. De ce nu declanşăm vizitarea unui obiect, apelând **direct** //​v.visit(e)//​ atunci când dorim vizitarea unui obiect oarecare? Răspunsul vine însă chiar din situaţiile în care vrem să folosim pattern-ul; vrem să lăsăm structura internă a colecţiei să facă aplicarea vizitatorilor. Cu alte cuvinte vizitatorul se ocupă de fiecare obiect în parte, iar colecţia îl "​plimbă"​ prin elementele sale. De exemplu, când dorim să vizităm un arbore: +
-  * declanşarea vizitării se va face printr-un apel ''​accept''​ pe un prim obiect (e.g. rădacina arborelui) +
-  * elementul curent este vizitat, prin apelul ''​v.visit(this)''​ +
-  * pe lângă vizitarea elementului curent, este necesar sa declanşăm vizitarea //tuturor elementelor accesibile din elementul curent// (e.g. nodurile-copil din arbore etc). Realizăm acest lucru apelând ''​accept''​ pe //fiecare// dintre aceste elemente. Acest comportament depinde de logica structurii. +
-</​note>​ +
- +
-=== Scenariu Visitor === +
- +
-Pentru a înţelege mai bine motivaţia din spatele design-pattern-ului //​Visitor//,​ să considerăm următorul exemplu. +
- +
-== Before == +
- +
-Fie ierarhia de mai jos, ce defineşte un angajat (//​Employee//​) şi un şef (//​Manager//​),​ văzut, de asemenea, ca un angajat: +
- +
-<code java Test.java>​ +
-class Employee { +
-        String ​ name; +
-        float   ​salary; ​        +
-        public Employee(String name, float salary) { +
-                this.name ​      = name; +
-                this.salary ​    = salary; +
-        } +
-        public String getName() { +
-                return name; +
-        } +
-        public float getSalary() { +
-                return salary; +
-        } +
-+
-class Manager extends Employee {         +
-        float bonus; +
-        public Manager(String name, float salary) { +
-                super(name, salary); +
-                bonus = 0; +
-        }         +
-        public float getBonus() { +
-                return bonus; +
-        } +
-        public void setBonus(float bonus) { +
-                this.bonus = bonus; +
-        } +
-+
-public class Test { +
-        public static void main(String[] args) { +
-                Manager manager; +
-                List<​Employee>​ employees = new LinkedList<​Employee>​(); ​                +
-                employees.add(new Employee("​Alice",​ 20)); +
-                employees.add(manager= new Manager("​Bob",​ 1000)); +
-                manager.setBonus(100);​ +
-        } +
-+
-</​code>​ +
- +
-Ne interesează să interogăm toţi angajaţii noştri asupra //venitului lor total//. Observăm că: +
-  * anagajaţii obişnuiţi au salariul ca unic venit +
-  * şefii posedă, pe lângă salariu, un posibil bonus +
- +
-Varianta la îndemână ar fi să definim, în fiecare din cele doua clase, câte o metodă, //​getTotalRevenue()//,​ care întoarce salariul pentru angajaţi, respectiv suma dintre salariu şi bonus pentru şefi: +
- +
-<code java> +
-class Employee { +
-        ... +
-        public float getTotalRevenue() { +
-                return salary; +
-        } +
-+
-class Manager extends Employee { +
-        ...        +
-        public float getTotalRevenue() { +
-                return salary + bonus; +
-        } +
-+
-</​code>​ +
- +
-Acum ne interesează să calculăm //procentul mediu// pe care îl reprezintă bonusul din venitul şefilor, luându-se în considerare doar bonusurile pozitive. Avem două posibilităţi:​ +
-  * Definim câte o metodă, //​getBonusPercentage()//,​ care în //​Employee//​ întoarce mereu 0, iar în //Manager// raportul real. **Dezavantajul** constă în adăugarea în interfeţe a unor funcţii prea specializate,​ de detalii ce ţin doar de unele implementări ale acestora. +
-  * Parcurgem lista de angajaţi, //​testăm//,​ la fiecare pas, tipul angajatului,​ folosind ''​instanceof'',​ şi calculăm, doar pentru şefi, raportul solicitat. **Dezavantajul** este tratarea într-o manieră //​neuniformă//​ a structurii noastre, cu evidenţierea particularităţilor fiecărei clase. +
- +
-Datorită acestor particularităţi (în cazul nostru, modalităţile de calcul al venitului, respectiv procentului mediu), constatăm că ar fi foarte utilă **izolarea implementărilor specifice** ale algoritmului (în cazul nostru, scrierea unei funcţii în fiecare clasă). Acest lucru conduce, însă, la introducerea unei metode noi în //fiecare// din clasele antrenate in prelucrări,​ de fiecare dată cand vrem să punem la dispoziţie o nouă operaţie. Obţinem următoarele dezavantaje:​ +
-  * în cazul unui număr mare de operaţii, **interfeţele claselor se aglomerează excesiv** şi se ascunde funcţionalitatea //de bază// a acestora +
-  * codul din interiorul clasei (care servea functionalităţii primare a acesteia) va fi amestecat cu cel necesar algoritmilor de prelucrare, devenind mai greu de parcurs şi întreţinut +
-  * în cazul în care nu avem acces la codul claselor, singura modalitate de adăugare de funcţionalitate este extinderea +
- +
-În final, tragem concluzia că este de dorit să **izolăm algoritmii de clasele pe care le prelucrează**. +
- +
-O abordare bună ar fi: +
-  * conceperea claselor cu **posibilitatea de primire/​ataşare a unor obiecte-algoritm**,​ care definesc operaţiile dorite +
-  * definirea unor **clase algoritm** care vor __//​**vizita**//​__ structura noastră de date, vor //efectua// prelucrările specifice fiecărei clase, având, totodată, //​posibilitatea de încapsulare a unor informaţii de stare// (cum sunt suma şi numărul din exemplul anterior) +
- +
-== After == +
-Conform observațiilor precedente, structura programului Employee-Manager devine: +
- +
-<code java Test.java>​ +
-interface Visitor { +
-        public void visit(Employee employee);​ +
-        public void visit(Manager manager); +
-+
-interface Visitable { +
-        public void accept(Visitor v); +
-+
-class Employee implements Visitable { +
-        ...       +
-        public void accept(Visitor v) { +
-                v.visit(this); ​          +
-        } +
-+
-class Manager extends Employee { +
-        ... +
-        public void accept(Visitor v) { +
-                v.visit(this); ​          +
-        } +
-+
-public class Test { +
-        public static void main(String[] args) { +
-                ... +
-                Visitor v = new SomeVisitor(); ​       // creeaza un obiect-vizitator concret +
-                for (Employee e : employees) +
-                        e.accept(v); ​                +
-        } +
-+
-</​code>​ +
- +
-Iată cum poate arăta un vizitator ce determină venitul total al fiecărui angajat şi îl afişează:​ +
-<code java RevenueVisitor.java>​ +
-public class RevenueVisitor implements Visitor {         +
-        public void visit(Employee employee) { +
-                System.out.println(employee.getName() + " " + employee.getSalary()); ​                +
-        }         +
-        public void visit(Manager manager) { +
-                System.out.println(manager.getName() + " " + (manager.getSalary() + manager.getBonus())); ​                +
-        }        +
-+
-</​code>​ +
- +
-Secvenţele de cod de mai sus definesc: +
-  * o interfaţă,​ **Visitor**,​ ce reprezintă un //​algoritm//​ oarecare, ce va putea vizita orice clasă. Observaţi definirea câte //unei metode visit(...)//​ pentru //fiecare clasă ce va putea fi vizitată//​ +
-  * o interfaţă,​ **Visitable**,​ a carei metodă ''​accept(Visitor)''​ permite rularea unui algoritm pe structura curentă.  +
-  * implementări ale metodei ''​accept(Visitor)'',​ în cele două clase, care, pur şi simplu, solicită vizitarea instanţei curente de către vizitator.  +
-  * o implementare a unei operații aplicabilă pe obiectele de tip Visitable +
- +
-În exemplul de mai sus, putem identifica : +
-  * Element - Visitable +
-  * ConcreteElement - Employee, Manager +
- +
-=== Double-dispatch === +
- +
-Mecanismul din spatele pattern-ului Visitor poartă numele de **double-dispatch**. Acesta este un concept raspândit, şi se referă la faptul că metoda apelată este determinată la //runtime// de doi factori. În exemplul Employee-Manager,​ efectul vizitarii, solicitate prin apelul ''​e.accept(v)'',​ depinde de: +
-  * tipul elementului vizitat, ''​e''​ (//​Employee//​ sau //​Manager//​),​ pe care se invocă metoda +
-  * tipul vizitatorului,​ ''​v''​ (//​RevenueVisitor//​),​ care conţine implementările metodelor //visit// +
- +
-Acest lucru contrastează cu un simplu apel //​e.getTotalRevenue()//,​ pentru care efectul este hotărât doar de tipul anagajatului. Acesta este un exemplu de **single-dispatch**.  +
- +
-<​note>​[[:​poo-ca-cd::​laboratoare:​tutorial-doubledispatch| Tutorialul de double-dispatch]] oferă mai multe detalii legate de acest mecanism.</​note>​ +
- +
-=== Cum implementăm?​ === +
- +
-  - Se declară interfața care să reprezinte elementul nostru, care va conține și metoda ''​public void accept(ElementVisitor elementVisitor);''​ +
-  - Se creează clasele concrete care implementează interfața declarată anterior. Body-ul pentru metoda accept va conține obligatoriu ''​elementVisitor.visit(this);''​ +
-  - Se definește o interfață care reprezintă Visitor-ul nostru și care va conține atâtea metode de visit câte clase concrete am creat la pasul anterior (câte o metodă de visit pentru fiecare tip de element). +
-  - Se creează o clasă concretă care implementează interfața de Visitor, unde vom adăuga implementările pentru fiecare tip de element în parte. (ex: ''​ElementDisplayVisitor()''​) +
-  - În main putem testa dacă funcționează așa cum ne dorim iterând print-un arraylist/​vector de obiecte de tip Element astfel: ''​elementIterator.accept(new ElementDisplayVisitor());''​ +
- +
-=== Avantaje și dezavantaje === +
- +
-**Avantaje:​** +
-  * Decuplarea datelor de operațiile aplicate pe acestea +
-  * Ușurează adăugarea unor noi operații/​algortimi. Se creează o implementare a unui obiect de tip Visitor și nu se schimbă nimic în obiecte vizitate. +
-  * Spre deosebire de Iterator poate gestiona elemente de tipuri diferite +
-  * Poate menține informații de stare pe măsură ce vizitează obiectele +
- +
-**Dezavantaje:​** +
-  * Depinde de stabilitatea ierarhiei de obiecte vizitate. Adăugarea de obiecte vizitabile rezultă în schimbarea implementării obiectelor Visitor.  +
-  * :!: obiecte de noi tipuri adăugate des + multe operații aplicabile = NU folosiți Visitor +
-  * Expune metode publice care folosesc informații de stare ale obiectelor. Nu se pot accesa membrii privați ai claselor, necesitatea expunerii acestor informaţii (in forma publică) ar putea conduce la //ruperea încapsulării//​ +
- +
-==== Exemple din API-uri ==== +
- +
-Visitor este de obicei utilizat pentru structuri arborescente de obiecte: +
-  * Parcurgerea arborilor de parsare +
-     * [[https://​help.eclipse.org/​neon/​index.jsp?​topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTVisitor.html| ASTVisitor]] din Eclipse JDT. Folosind [[http://​help.eclipse.org/​neon/​index.jsp?​topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTParser.html|ASTParser]] se creează arborele de parsare al codului dat ca intrare, iar [[https://​help.eclipse.org/​neon/​index.jsp?​topic=%2Forg.eclipse.jdt.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjdt%2Fcore%2Fdom%2FASTVisitor.html|ASTVisitor]] parcurge arborele, oferind metode (//​preVisit//,​ //​postVisit//,​ //visit//) pentru multe tipuri de noduri (MethodDeclaration,​ Assignment, IfStatement etc.) +
-  * Parcurgerea și vizitarea ierarhiei de directoare și fișiere +
-     * Java Nio - [[https://​docs.oracle.com/​en/​java/​javase/​12/​docs/​api/​java.base/​java/​nio/​file/​FileVisitor.html | FileVisitor]] +
-        * //​FileVisitor//​ - interfața cu metode de vizitare +
-        * trebuie apelat [[https://​docs.oracle.com/​en/​java/​javase/​12/​docs/​api/​java.base/​java/​nio/​file/​Files.html#​walkFileTree(java.nio.file.Path,​java.nio.file.FileVisitor) | Files.walkFileTree]] transmițându-i ca parametru un obiect care implementează //​FileVisitor//​ +
-        * [[http://​docs.oracle.com/​javase/​tutorial/​essential/​io/​walk.html | un tutorial]]  +
- +
-==== Summary ==== +
- +
-**Visitor** = behavioral design pattern +
-  * Util în situații în care: +
-      * avem mai multe obiecte și operații pentru acestea +
-      * dorim schimbarea/​adăugarea operațiilor fără a modifica clasele +
-  * Indicat de utilizat pentru operații pe colecții și parcurgerea de structuri arborescente +
-  * Folosește conceptul de [[:​poo-ca-cd:​laboratoare:​tutorial-doubledispatch|double dispatch]] +
-   +
-==== Exerciţii ==== +
- +
-Dorim să prelucrăm bucăți de text pe care să le convertim în diferite formate, momentan dokuwiki și markdown. Pentru un design decuplat între obiectele prelucrate și tipurile de formate dorite, implementați conversia folosind patternul Visitor. +
- +
-      * Fișierul **[[https://​github.com/​oop-pub/​oop-labs/​tree/​master/​src/​lab7|README]]** din scheletul de cod cuprinde informațiile necesare designului dorit. +
-        * implementați structura de clase din diagrama din README +
-        * implementați TODO-urile din scheletul de cod +
-      * Pentru simplitatea testării scheletul oferă clasa ''​Test''​ care oferă bucățile de text pe care să le prelucrați. +
-        * dacă folosiți IntelliJ creați proiect din scheletul de laborator: File -> New Project -> select Java -> select the skel folder +
-      * În implementare va trebui sa folositi clasa [[https://​docs.oracle.com/​en/​java/​javase/​12/​docs/​api/​java.base/​java/​lang/​StringBuilder.html|StringBuilder]]. Aceasta este o clasă mutabilă (//​mutable//​),​ spre deosebire de String, care e imutabilă (//​immutable//​). Vă recomandăm [[https://​www.geeksforgeeks.org/​string-vs-stringbuilder-vs-stringbuffer-in-java/​|acest link]] pentru un exemplu si explicații despre diferențele dintre ele. +
-      * //Tips for faster coding//: +
-        * atunci cand creati o clasa care implementeaza o interfata sau o clasa cu metode abstracte, nu scrieti de mana antetul fiecarei metode, ci folositi-va de IDE. +
-        * In Intellij va aparea cu rosu imediat dupa ce scrieti extends.../​implements... Dati alt-enter sau option-enter (pe mac), si vi se vor genera metodele pe care trebuie sa le implementati,​ voi completand apoi continutul lor. +
-        * generati constructorii folosind IDE-ul +
- +
- +
- +
-==== Referințe ==== +
-  - Vlissides, John, et al. //Design patterns: Elements of reusable object-oriented software//. Addison-Wesley (1995) ([[http://​index-of.co.uk/​Software-Engineering/​Design%20Patterns%20-%20Elements%20Of%20Reusable%20Object-Oriented%20Software%20-%20Addison%20Wesley.pdf|available online]]) +
-  - [[http://​en.wikipedia.org/​wiki/​Software_design_pattern | Clasificarea design pattern-urilor]] +
-  - [[:​poo-ca-cd:​laboratoare:​tutorial-doubledispatch| Tutorial double-dispatch]]+
  
 +**Video introductiv:​** [[https://​youtu.be/​KIyaRwog3q8| link ]]
  
 +**Slides din video**:​{{:​poo-ca-cd:​laboratoare:​clase-interne:​laborator_6_-_clase_interne.pdf| link}}
 ==== Obiective ==== ==== Obiective ====
  
Line 430: Line 153:
 Când veți scrie o clasă anonimă într-un IDE cum e IntelliJ, veți primi un warning care vă recomandă să o transformați într-o lambda. Aceasta recomandare este valabilă doar pentru implementarea claselor/​interfețelor cu o singură metoda. Când veți scrie o clasă anonimă într-un IDE cum e IntelliJ, veți primi un warning care vă recomandă să o transformați într-o lambda. Aceasta recomandare este valabilă doar pentru implementarea claselor/​interfețelor cu o singură metoda.
  
-Lambda este un concept din programarea funcțională (o să îl învățați în semestrul 2 la Paradigme de Programare) și reprezintă o funcție anonimă. Majoritatea limbajelor de nivel înalt au introdus suport pentru acest concept în ultimii 15 ani, inclusiv Java, din versiunea 8.+Lambda este un concept din **programarea funcțională** (o să îl învățați în semestrul 2 la Paradigme de Programare) și reprezintă o funcție anonimă. Majoritatea limbajelor de nivel înalt au introdus suport pentru acest concept în ultimii 15 ani, inclusiv Java, din versiunea 8.
  
  
Line 443: Line 166:
 </​code>​ </​code>​
  
-În codul de mai sus declararea clasei anonime și suprascrierea metodei din getFuelCapacity() a fost înlocuită cu o expresie lambda. O altă situație des intalnită de folosire a lambda-urilor este pentru transmiterea de funcții ca parametru iar api-uri precum cel de filtrare al colecțiilor le utilizează intens ([[https://​www.baeldung.com/​java-stream-filter-lambda|exemplu]]).+În codul de mai sus declararea clasei anonime și suprascrierea metodei din getFuelCapacity() a fost înlocuită cu o expresie lambda. O altă situație des intalnită de folosire a lambda-urilor este pentru ​**transmiterea de funcții ca parametru** iar api-uri precum cel de filtrare al colecțiilor le utilizează intens ([[https://​www.baeldung.com/​java-stream-filter-lambda|exemplu]]). 
  
 În exemplul de mai jos aveți niște exemple simple de folosire lambda ca paremetru pentru metode. Parametrii primiți în lambda pot fi zero (//()// ca în exemplul cu fuelCapacity) sau mai mulți (param1, param2, ...).  În exemplul de mai jos aveți niște exemple simple de folosire lambda ca paremetru pentru metode. Parametrii primiți în lambda pot fi zero (//()// ca în exemplul cu fuelCapacity) sau mai mulți (param1, param2, ...). 
Line 459: Line 183:
 </​code>​ </​code>​
  
-Operatorul [[https://​www.geeksforgeeks.org/​double-colon-operator-in-java/​|::​]] este folosit pentru referințierea metodelor.+**Operatorul [[https://​www.geeksforgeeks.org/​double-colon-operator-in-java/​|::​]]** este folosit pentru referințierea metodelor
 +  
 +Putem folosi funcții anonime pentru a executa diverse **operații pe liste** (de exemplu ''​removeIf'',​ care filtrează elementele unei colecții pe baza unui predicat, și ''​replaceAll'',​ care aplică o operație pe toate elementele unei colecții).
  
-O să mai oferim exemple și detalii despre lambdas și în laboratoarele următoarede exemplu cel cu [[poo-ca-cd:​laboratoare:​colectii|Colecții]] sau cel pentru concepte ​din [[poo-ca-cd:​laboratoare:​java-features|Java 8]].+Exemple: 
 +<code java> 
 +List<​Integer>​ list = new ArrayList<>​(Arrays.asList(12, 3, 4, 5, 6, 7, 8, 9, 10)); 
 + 
 +// incrementează toate numerele din colecție ​cu 
 +list.replaceAll((x) ​-> x + 1); 
 + 
 +// șterge ​din colecție numerele impare 
 +list.removeIf((x) -> x % 2 == 1); 
 +</​code>​
  
 +O altă utilitate a funcțiilor anonime reprezintă în **implementarea comparatorilor** folosiți la sortare sau la crearea de colecții sortate (TreeSet, TreeMap).
 +
 +Exemple:
 +<code java>
 +// o variantă
 +Collections.sort(list,​ (o1, o2) -> o2 - o1);
 +
 +// alta variantă, prin care se folosim de metoda sort() din interfața List
 +list.sort((o1,​ o2) -> o2 - o1);
 +
 +// colecții sortate
 +TreeSet<​Integer>​ sortedSet = new TreeSet<>​((o1,​ o2) -> o1 - o2);
 +TreeMap<​Integer,​ Integer> sortedMap = new TreeMap<>​((o1,​ o2) -> o1 - o2);
 +</​code>​
 ====Clase interne statice==== ====Clase interne statice====
  
Line 634: Line 383:
  }  }
     });</​code>​     });</​code>​
-==== Exerciții ====  +==== Exerciții ====
-/***Task 1 - Meta** (4p)+
  
-Îndrumarul este o componentă importantă a laboratorului de POO, iar citirea și înțelegerea acestuia nu trebuie neglijate. În îndrumarul ​din acest laborator ​există mai multe căsuțde tip **note**, ​de forma celei de mai jos:+Exercițiile din acest laborator ​au ca scop simularea obținerii prețului unei mașini ​de la un dealer. Construcția obiectelor necesare o veți face de la zero conform instrucțiunilor din taskuri.
  
-<note> Do stuff </note+<​note ​important
- +Pentru a încărca soluțiava trebui să accesați link-ul ​https://code.devmind.ro/login, să intrați pe tab-ul Contests, unde veți găsi laboratorul grupei voastre. 
-Identificați toate căsuțele de tip **note** din laborator și urmați instrucțiunile din acestea. Puteți folosi scheletul pus la dispoziție. Pentru a ușura procesul de evaluarecreați fișiere separate pentru fiecare task din **note**. +</​note>​
-*/ +
- +
-**Schelet de laborator**:​ [[https://github.com/oop-pub/​oop-labs/​tree/​master/​src/​lab6|Laborator6]] +
- +
-Exercițiile din acest laborator au ca scop simularea obținerii prețului unei mașini de la un dealer. Construcția obiectelor necesare o veți face de la zero conform instrucțiunilor din taskuri.+
  
  
poo-ca-cd/laboratoare/clase-interne.1731249411.txt.gz · Last modified: 2024/11/10 16:36 by silvia_elena.nistor
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0