User Tools

Site Tools


Problem constructing authldap
laboratoare:visitor
Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
laboratoare:visitor [2018/09/25 11:41]
Tudor Paraschivescu [Resurse]
laboratoare:visitor [2019/11/10 19:12]
Adriana Draghici [Exerciţii]
Line 1: Line 1:
-More OOP & Visitor pattern =+Overriding, Overloading ​& Visitor pattern =
  
 == Obiective ==  == Obiective == 
Line 79: Line 79:
 Suprascrierea se referă la redefinirea metodelor existente în clasa părinte de către clasa copil în vederea specializării acestora. Metodele din clasa parinte nu sunt modificate. Putem suprascrie doar metodele vizibile pe lanțul de moștenire (public, protected). O metodă din clasa copil suprascrie metoda din clasa părinte dacă are același tip de return și aceeași semnatură (nume și parametri). Suprascrierea se referă la redefinirea metodelor existente în clasa părinte de către clasa copil în vederea specializării acestora. Metodele din clasa parinte nu sunt modificate. Putem suprascrie doar metodele vizibile pe lanțul de moștenire (public, protected). O metodă din clasa copil suprascrie metoda din clasa părinte dacă are același tip de return și aceeași semnatură (nume și parametri).
  
-Spre deosebire de supraîncărcare care face acest lucru la compilare, în cazul suprascrierii se determină ce metodă va fi apelată, în mod dinamic, **la runtime**. Explicația este că decizia se face pe baza__ tipului obiectului__ care apelează metoda, deci a instanței (cunoscută la runtime). Din acest motiv, suprascrierea este cunoscută și ca polimorfism dinamic (''​Runtime polymorphism''​). Polimorfismul reprezintă abilitatea unei clase să se comporte ca o altă clasă de pe lanțul de moștenire, și de aceea conceptul de suprascriere a metodelor este foarte strâns legat. Supraîncărcarea,​ fiind la compile-time,​ nu are legătură cu acest polimorfism dinamic.+Spre deosebire de supraîncărcare care face acest lucru la compilare, în cazul suprascrierii se determină ce metodă va fi apelată, în mod dinamic, **la runtime**. Explicația este că decizia se face pe baza__ tipului obiectului__ care apelează metoda, deci a instanței (cunoscută la runtime). Din acest motiv, suprascrierea este cunoscută și ca polimorfism dinamic (''​Runtime polymorphism''​). ​**Polimorfismul reprezintă abilitatea unei clase să se comporte ca o altă clasă de pe lanțul de moștenire, și de aceea conceptul de suprascriere a metodelor este foarte strâns legat. Supraîncărcarea,​ fiind la compile-time,​ nu are legătură cu acest polimorfism dinamic.**
  
 <note important>​ La apelarea unei metode suprascrise,​ Java se uită la tipul intern al obiectului pentru care este apelată metoda, NU la referință. Astfel dacă referința are tipul clasei părinte, dar tipul este al clasei copil, JVM va apela metoda din clasa copil. </​note>​ <note important>​ La apelarea unei metode suprascrise,​ Java se uită la tipul intern al obiectului pentru care este apelată metoda, NU la referință. Astfel dacă referința are tipul clasei părinte, dar tipul este al clasei copil, JVM va apela metoda din clasa copil. </​note>​
Line 150: Line 150:
 </​note>​ </​note>​
  
 +=== super ===
  
-== Cuvântul ​cheie super și overriding == +În laboratorul [[laboratoare:​agregare-mostenire#​cuvantul-cheie-super-intrebuintari|]] ​am folosit cuvântul cheie **super** pentru a invoca un anumit constructor din clasa părinte ​dar și pentru ​a apela în mod explicit metoda din clasa părinte în cazul metodelor suprascrise.
- +
-În laboratoarele trecute ​am folosit cuvântul cheie //super// pentru a invoca un anumit constructor din clasa părinte+
- +
-O alta utilizare a lui //super// este de a apela in mod explicit metoda din clasa părinte în cazul metodelor suprascrise.+
  
 Rescriem metoda ''​purr()''​ din clasa ''​GrumpyCat''​ astfel: Rescriem metoda ''​purr()''​ din clasa ''​GrumpyCat''​ astfel:
Line 165: Line 162:
 } }
 </​code>​ </​code>​
-La apelul metodei pe o instanță a clasei''​ GrumpyCat''​ output-ul va fi:+La apelul metodei pe o instanță a clasei ''​GrumpyCat''​ output-ul va fi:
 <​code>​ <​code>​
 purrrr purrrr
Line 220: Line 217:
 ==== Before ==== ==== Before ====
  
-Fie ierarhia de mai jos, ce defineşte un angajat (//​Employee//​) şi un şef (//Boss//), văzut, de asemenea, ca un angajat:+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>​ <code java Test.java>​
Line 237: Line 234:
         }         }
 } }
-class Boss extends Employee {        ​+class Manager ​extends Employee {        ​
         float bonus;         float bonus;
-        public ​Boss(String name, float salary) {+        public ​Manager(String name, float salary) {
                 super(name, salary);                 super(name, salary);
                 bonus = 0;                 bonus = 0;
Line 252: Line 249:
 public class Test { public class Test {
         public static void main(String[] args) {         public static void main(String[] args) {
-                ​Boss boss;+                ​Manager manager;
                 List<​Employee>​ employees = new LinkedList<​Employee>​(); ​               ​                 List<​Employee>​ employees = new LinkedList<​Employee>​(); ​               ​
                 employees.add(new Employee("​Alice",​ 20));                 employees.add(new Employee("​Alice",​ 20));
-                employees.add(boss = new Boss("​Bob",​ 1000)); +                employees.add(manager= new Manager("​Bob",​ 1000)); 
-                ​boss.setBonus(100);​+                ​manager.setBonus(100);​
         }         }
 } }
Line 274: Line 271:
         }         }
 } }
-class Boss extends Employee {+class Manager ​extends Employee {
         ...                ...       
         public float getTotalRevenue() {         public float getTotalRevenue() {
Line 283: Line 280:
  
 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:​ 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 //Boss// 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.+  * 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.   * 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.
  
Line 291: Line 288:
   * în cazul în care nu avem acces la codul claselor, singura modalitate de adăugare de funcţionalitate este extinderea   * î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 primă idee se referă la utilizarea //metodelor statice//. Dezavantajul acestora este că nu pot reţine, într-un mod elegant, informaţie de stare din timpul prelucrării. De exemplu, dacă structura noastră ar fi arborescentă (recursivă),​ în sensul că o instanţă //Boss// ar putea ţine referinţe la alte instanţe //Boss//, ce reprezintă şefii ierarhic inferiori, o funcţie de prelucrare ar trebui să menţină o informaţie parţială de stare (precum suma procentelor calculate până într-un anumit moment) sub forma unor parametri furnizaţi apelului recursiv:+În final, tragem concluzia că este de dorit să **izolăm algoritmii de clasele pe care le prelucrează**. O primă idee se referă la utilizarea //metodelor statice//. Dezavantajul acestora este că nu pot reţine, într-un mod elegant, informaţie de stare din timpul prelucrării. De exemplu, dacă structura noastră ar fi arborescentă (recursivă),​ în sensul că o instanţă //Manager// ar putea ţine referinţe la alte instanţe //Manager//, ce reprezintă şefii ierarhic inferiori, o funcţie de prelucrare ar trebui să menţină o informaţie parţială de stare (precum suma procentelor calculate până într-un anumit moment) sub forma unor parametri furnizaţi apelului recursiv:
 <code java> <code java>
-class Boss extends Employee {+class Manager ​extends Employee {
         ...         ...
         public float getPercentage(float sum, int n) {         public float getPercentage(float sum, int n) {
                 float f = bonus / getTotalRevenue();​                 float f = bonus / getTotalRevenue();​
                 if (f > 0)                 if (f > 0)
-                        return ​inferiorBoss.getPercentage(sum + f, n + 1); // trimite mai departe cererea catre nivelul inferior ​                +                        return ​inferiorManager.getPercentage(sum + f, n + 1); // trimite mai departe cererea catre nivelul inferior ​                
-                return ​inferiorBoss.getPercentage(sum,​ n);+                return ​inferiorManager.getPercentage(sum,​ n);
         }        ​         }        ​
 } }
Line 309: Line 306:
  
 ==== After ==== ==== After ====
-Conform observațiilor precedente, structura programului Employee-Boss devine:+Conform observațiilor precedente, structura programului Employee-Manager ​devine:
  
 <code java Test.java>​ <code java Test.java>​
 interface Visitor { interface Visitor {
-        public void visit(Employee ​e); +        public void visit(Employee ​employee); 
-        public void visit(Boss b);+        public void visit(Manager manager);
 } }
 interface Visitable { interface Visitable {
Line 325: Line 322:
         }         }
 } }
-class Boss extends Employee {+class Manager ​extends Employee {
         ...         ...
         public void accept(Visitor v) {         public void accept(Visitor v) {
Line 344: Line 341:
 <code java RevenueVisitor.java>​ <code java RevenueVisitor.java>​
 public class RevenueVisitor implements Visitor {        ​ public class RevenueVisitor implements Visitor {        ​
-        public void visit(Employee ​e) { +        public void visit(Employee ​employee) { 
-                System.out.println(e.getName() + " " + e.getSalary()); ​               ​+                System.out.println(employee.getName() + " " + employee.getSalary()); ​               ​
         }        ​         }        ​
-        public void visit(Boss b) { +        public void visit(Manager manager) { 
-                System.out.println(b.getName() + " " + (b.getSalary() + b.getBonus())); ​               ​+                System.out.println(manager.getName() + " " + (manager.getSalary() + manager.getBonus())); ​               ​
         }                }       
 } }
Line 361: Line 358:
 În exemplul de mai sus, putem identifica : În exemplul de mai sus, putem identifica :
   * Element - Visitable   * Element - Visitable
-  * ConcreteElement - Employee, ​Boss+  * ConcreteElement - Employee, ​Manager
  
 === Double-dispatch === === 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-Boss, efectul vizitarii, solicitate prin apelul ''​e.accept(v)'',​ depinde de: +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 //Boss//), pe care se invocă metoda+  * tipul elementului vizitat, ''​e''​ (//​Employee//​ sau //Manager//), pe care se invocă metoda
   * tipul vizitatorului,​ ''​v''​ (//​RevenueVisitor//​),​ care conţine implementările metodelor //visit//   * tipul vizitatorului,​ ''​v''​ (//​RevenueVisitor//​),​ care conţine implementările metodelor //visit//
  
Line 404: Line 401:
         * [[http://​docs.oracle.com/​javase/​tutorial/​essential/​io/​walk.html | un tutorial]] ​         * [[http://​docs.oracle.com/​javase/​tutorial/​essential/​io/​walk.html | un tutorial]] ​
  
-== TL;DR ==+== Summary ​==
  
 **Supraîncărcarea (overloading) ** - mai multe metode cu același nume dar cu listă diferită de argumente **Supraîncărcarea (overloading) ** - mai multe metode cu același nume dar cu listă diferită de argumente
Line 433: Line 430:
   ​   ​
 == Exerciţii == == Exerciţii ==
-  - **(1p)** Fișierul //​Examples//​ din scheletul de laborator conține exemple de overriding și overloading. Modificați codul din el astfel încât ​să poată fi compilat. Observați output-ul. + 
-    - Cum vă explicați output-ul ''​Constructor As = hi this = B@5ad557c2''​ ? Revedeț[[.:​visitor#​overriding|nota din sectiunea Overriding]] pentru o explicație. +** Task 1 ** [8p] 
-    - Ce va afișa apelul ''​c.f()''?​ (gândiți-vă voi fără să rulați+ 
-    - Care 2 linii le afișează ''​new Examples().test(a2);''​ și de ce? +Dorim să prelucrăm bucăți de text pe care să le convertim în diferite formatemomentan dokuwiki șmarkdownPentru un design decuplat între obiectele prelucrate ​și tipurile de formate dorite, implementați conversia folosind patternul Visitor
-  ​- ​**(1p)** Scheletul de laborator conține implementarea folosind pattern-ul Visitor a scenariului Employee-Boss descris ​[[.:​visitor#​scenariu-visitor| ​mai sus]]. Spre deosebire ​de exemplele din laborator, clasa Employee conține și câmpul extraHours, relevant pentru exercițiul 3+ 
-         ​a) Rulați codul și observați comportamentul și interacțiunea dintre obiectele vizitate și obiectul ​de tip Visitor. +Fișierul ​**[[https://​github.com/oop-pub/​laboratoare/​tree/​master/​visitor/skel|README]]** din scheletul ​de cod cuprinde informațiile necesare designului dorit
-         ​b) Nu mai suprascrieți metoda ''​accept'' ​din //Boss//, rulați și explicați rezultatul execuției. +   ​implementați structura ​de clase din diagrama din README 
-  ​- ​**(5p)** Obiectele Employee-Boss pot fi reprezentate printr-o structură arborescentă, ce are ca rădăcină un Boss (ceo-ul). Creați un Visitor ​care să permită parcurgerea ierarhiei și efectuarea unei acțiuni pe fiecare nod. Acea acțiune este practic o operație, implementată într-o altă clasă ​de tip Visitor, deci TreeVisitor-ul va primi un obiect de tip Visitor ​pe care să îl aplice pe nodurile parcurse+   ​implementați TODO-urile ​din scheletul de cod 
-       ​fiecare //Boss// va ţine referinţe către angajaţii aflaţsub răspunderea lui directă (ce pot fi alţșefi la rândul lor, sau salariaţi obişnuiţi) +Pentru simplitatea testării scheletul oferă clasa ''​Test'' ​care oferă bucățile de text pe care să le prelucrați
-       ​implementați un //TreeVisitor// care pentru: +   ​dacă folosițIntelliJ creațproiect din scheletul de laborator: File -> New Project -> select Java -> select the skel folder 
-             ​* ​//Employee// - aplică operația primită  +Î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. 
-             ​* ​//Boss// - parcurge subordonații și apoi aplică operația primită pe Boss + 
-       * implementați un visitor ​(numit //MostHardworkingEmployeeFinder//) care compară numărul mediu de ore suplimentare pentru angajați cu cel pentru șefi.  + 
-   - **(3p)** Adăugați încă un tip de obiect vizitabil - //Intern//. Acesta nu are salariu și extra hours, doar nume și durata (în lunia internship-ului +** Task 2 ** - Utilizare API implementat folosind Visitor [2p] 
-       * modificați clasele existente deja, pentru a lua în considerare și obiectele Intern + 
-       * testați operațiile de la exercițiile anterioare pe o colecție care conține și obiecte Intern  +Afișați folosind ​''​java.nio''​ informații despre ​fișierele cu extensia "​.class" sau ".java" dintr-un director.  
-       * :!: Observați modificările pe care le-ați efectuat pentru a adăuga o nouă operație (ex2) și pe cele pentru ​a adăuga ​un nou tip de obiect în colecție. Ca să merite să aplicăm pattern-ul Visitor, ce situație ar trebui să fie evitată? +  Implementați un [[https://​docs.oracle.com/en/java/javase/12/docs/api/java.base/java/​nio/​file/​FileVisitor.html | FileVisitor]],​ extinzând [[https://​docs.oracle.com/en/java/javase/12/docs/api/java.base/​java/​nio/​file/​SimpleFileVisitor.html | SimpleFileVisitor]] în care suprascrieți metoda de vizitare a fișierelor  
-   - **(bonus - 2p)** Găsiți folosind java.nio ​toate fișierele cu extensia "​.class"​ dintr-un director.  +  Un exemplu similar găsiți în [[http://​docs.oracle.com/​javase/​tutorial/​essential/​io/​walk.html | acest tutorial]]
-       ​implementați un [[http://​docs.oracle.com/​javase/​8/docs/api/index.html?java/​nio/​file/​FileVisitor.html | FileVisitor]],​ extinzând [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​nio/​file/​SimpleFileVisitor.html | SimpleFileVisitor]] în care suprascrieți metoda de vizitare a fișierelor  +
-        un exemplu similar găsiți în [[http://​docs.oracle.com/​javase/​tutorial/​essential/​io/​walk.html | acest tutorial]] +
-        * Clasele din API-ul //​nio// ​ folosite pentru acest exercițiu sunt disponibile începând cu jdk7.+
  
 == Resurse == == Resurse ==
-* {{.:​visitor:​visitor-skel.zip| Schelet cod}} + 
-<​html><​a class="​media mediafile mf_pdf"​ href="/poo/​laboratoare/​visitor?​do=export_pdf">​PDF laborator<​/a></html>+* {{{ :​laboratoare:visitor:lab-visitor-skel.zip |Schelet ​de cod}} 
 +[[laboratoare:​old-exercises|Exerciții din alți ani]] 
 +* [[https://​github.com/​oop-pub/​laboratoare/​tree/master/visitor|Github repository]] 
  
 == Referințe == == Referințe ==
     - Kathy Sierra, Bert Bates. //SCJP Sun Certified Programmer for Java™ 6 - Study Guide//. Chapter 2 - Object Orientation ([[http://​firozstar.tripod.com/​_darksiderg.pdf|available online]]) - moștenire, polimorfism,​ overriding, overloading + exemple de întrebări     - Kathy Sierra, Bert Bates. //SCJP Sun Certified Programmer for Java™ 6 - Study Guide//. Chapter 2 - Object Orientation ([[http://​firozstar.tripod.com/​_darksiderg.pdf|available online]]) - moștenire, polimorfism,​ overriding, overloading + exemple de întrebări
-  - Vlissides, John, et al. //Design patterns: Elements of reusable object-oriented software//. Addison-Wesley (1995)+  - Vlissides, John, et al. //Design patterns: Elements of reusable object-oriented software//. Addison-Wesley (1995) ([[https://​sophia.javeriana.edu.co/​~cbustaca/​docencia/​DSBP-2018-01/​recursos/​Erich%20Gamma,​%20Richard%20Helm,​%20Ralph%20Johnson,​%20John%20M.%20Vlissides-Design%20Patterns_%20Elements%20of%20Reusable%20Object-Oriented%20Software%20%20-Addison-Wesley%20Professional%20(1994).pdf|available online]])
   - [[http://​en.wikipedia.org/​wiki/​Software_design_pattern | Clasificarea design pattern-urilor]]   - [[http://​en.wikipedia.org/​wiki/​Software_design_pattern | Clasificarea design pattern-urilor]]
   - [[laboratoare:​tutorial-doubledispatch| Tutorial double-dispatch]]   - [[laboratoare:​tutorial-doubledispatch| Tutorial double-dispatch]]
  
  
laboratoare/visitor.txt · Last modified: 2019/11/30 12:17 by Adriana Draghici