Differences

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

Link to this comparison view

poo-ca-cd:laboratoare:agregare-mostenire [2020/10/03 14:06]
radu_bogdan.pavel [Resurse]
poo-ca-cd:laboratoare:agregare-mostenire [2022/10/24 10:40] (current)
diana.tatulescu [Exerciții]
Line 1: Line 1:
-===== Agregare și moștenire =====+===== Laboratorul 3: Agregare și moștenire =====
  
 +**Video introductiv:​** [[https://​www.youtube.com/​watch?​v=Gb-p4tMrdBM|link]]
  
 ==== Obiective ==== ==== Obiective ====
Line 30: Line 31:
 <code java> <code java>
 public class Foo { public class Foo {
-    // Obiectul Bar nu poate exista dacă obiectul Foo nu există+    // Obiectul ​de tip Bar nu poate exista dacă obiectul Foo nu există
     private Bar bar = new Bar();     private Bar bar = new Bar();
 } }
Line 39: Line 40:
     private Bar bar;      private Bar bar; 
     ​     ​
-    // Obiectul Bar poate continua să existe chiar dacă obiectul Foo nu există+    // Obiectul ​de tip Bar poate continua să existe chiar dacă obiectul Foo nu există
     Foo(Bar bar) {     Foo(Bar bar) {
        ​this.bar = bar;         ​this.bar = bar; 
Line 140: Line 141:
  
 // Obiectele Wind sunt instrumente // Obiectele Wind sunt instrumente
-// deoarece au aceeași interfață:​+// deoarece au ca si clasa-parinte clasa Instrument
 public class Wind extends Instrument { public class Wind extends Instrument {
     public static void main(String[] args) {     public static void main(String[] args) {
Line 182: Line 183:
 } }
  
-class Test {+public ​class Test {
     public static void main(String[] args) {     public static void main(String[] args) {
-        Animal ​[] = new Animal[2]; +        Animal[] ​animals ​= new Animal[2];
-         +
-        a[0] = new Wolf(); ​   // Upcasting automat +
-        a[1] = new Snake(); ​  // Upcasting automat+
  
-        for (int i = 0; i < a.length; i++) { +        ​animals[0] = new Wolf(); ​   // Upcasting automat 
-            ​a[i].eat(); // 1 +        animals[1] = new Snake(); ​  // Upcasting automat 
-             + 
-            if (a[i] instanceof Wolf) { +        ​for (int i = 0; i < animals.length; i++) { 
-                ((Wolf)a[i]).howl();​ // 2+            ​animals[i].eat(); // 1 
 + 
 +            if (animals[i] instanceof Wolf) { 
 +                ((Wolf)animals[i]).howl();​ // 2
             }             }
-                ​ + 
-            if (a[i] instanceof Snake) { +            if (animals[i] instanceof Snake) { 
-                ((Snake)a[i]).bite();​ // 3+                ((Snake)animals[i]).bite();​ // 3
             }             }
         }         }
     }     }
-+}
 </​code>​ </​code>​
  
Line 281: Line 282:
 Snake biting Snake biting
 </​code>​ </​code>​
 +
 +===De ce este instanceof considerat bad practice?​===
 +  * face codul repetitiv - downcasting și apelare de metodă la fiecare branch de if/else
 +  * face codul mai greu de întreținut pe termen lung - codul principal trebuie updatat de fiecare dată când se introduce o nouă subclasă (vezi exemplul de mai sus - introducerea unui noi clase derivate din  Animal va determina un alt branch de if/else)
 +  * face codul mai dificil de citit - este mult mai ușor să ne uităm la metodele suprascrise cu tag-ul @Override decât să căutam fiecare metoda cu un nume diferit pe rând
 +  * distruge designul orientat-obiect din perspectiva polimorfismului
 +  * încalcă [[https://​www.baeldung.com/​java-open-closed-principle|open-closed principle]]
 +  * nu poate fi folosit cu tipuri generice, ''​instanceof''​ fiind un **type comparison operator** ce va compara la runtime, în schimb genericitatea fiind rezolvată la compile-time. Mai multe detalii [[https://​www.baeldung.com/​java-instanceof#​generics|aici]] si in [[https://​ocw.cs.pub.ro/​courses/​poo-ca-cd/​laboratoare/​genericitate|laboratorul 11]] despre genericitate.
 +
 +**Soluții** pentru evitarea ''​instanceof'':​
 +   * polimorfism
 +   * [[https://​ocw.cs.pub.ro/​courses/​poo-ca-cd/​laboratoare/​visitor|Visitor]]
 +
 +
 +<note important>​
 +Când este necesar să folosim ''​instanceof''?​
 +
 +''​instanceof''​ poate fi folosit când nu controlăm ierarhia claselor și suntem obligați să facem
 +testarea tipului deoarece nu putem aplica polimorfismul - clasele provin dintr-o librărie externă.
 +</​note>​
  
   ​   ​
Line 357: Line 378:
 b.print(); // afișează Car pentru că tipul dat la inițializare al lui b este Car b.print(); // afișează Car pentru că tipul dat la inițializare al lui b este Car
 c.print(); // afișează Dacia pentru că tipul dat la inițializare al lui c este  Dacia c.print(); // afișează Dacia pentru că tipul dat la inițializare al lui c este  Dacia
-d.print(): // afișează Car pentru că tipul dat la inițializare al lui este Car+d.print(): // afișează Car pentru că tipul dat la inițializare al lui este Car
 </​code>​ </​code>​
  
Line 504: Line 525:
  
 <note important>​Chiar dacă nu se specifică apelul metodei ''​super()'',​ compilatorul va apela automat constructor-ul implicit al părintelui însă dacă se dorește apelarea altui constructor,​ apelul de ''​super(args)''​ respectiv este obligatoriu</​note>​ <note important>​Chiar dacă nu se specifică apelul metodei ''​super()'',​ compilatorul va apela automat constructor-ul implicit al părintelui însă dacă se dorește apelarea altui constructor,​ apelul de ''​super(args)''​ respectiv este obligatoriu</​note>​
 +
 +====Utilizarea clasei ArrayList. Exemple====
 +
 +Clasa ArrayList este un array redimensionabil,​ iar această clasă poate fi găsită în pachetul ''​java.util''​.
 +Principalele metode ale acestei clase sunt:
 +  * ''​add()''​ - adaugă un element la ArrayList.
 +  * ''​get()''​ - accesează elementul de pe o anumită poziție din ArrayList.
 +  * ''​size()''​ - returnează numărul de elemente din ArrayList.
 +  * ''​set()''​ - modifica un element de pe o anumită poziție din ArrayList. ​
 +  * ''​remove()''​ - șterge un element de pe o anumită poziție din ArrayList.
 +  * ''​clear()''​ - șterge toate elementele din ArrayList.
 +
 +Pentru a putea parcurge elementele unui ArrayList se poate folosit atât un for-each, cât și clasa Iterator.
 +Un exemplu de utilizare a metodelor clasei ArrayList și de parcurgere a elementelor stocate de această clasă este următorul:
 +
 +<code java5>
 +import java.util.ArrayList;​
 +import java.util.Iterator;​
 +
 +public class Main {
 +    public static void main(String[] args) { 
 +    ​
 +        ArrayList<​String>​ animals = new ArrayList<>​();​
 +        animals.add("​Dog"​);​
 +        animals.add("​Cat"​);​
 +        animals.add("​Sheep"​);​
 +    ​
 +        System.out.println("​First animal from the list is: " + animals.get(0));​
 +        System.out.println("​Number of animals from the list: " + animals.size());​
 +
 +        animals.set(0,​ "​Lion"​);​
 +        System.out.println("​First animal from the list is: " + animals.get(0));​
 +        ​
 +        animals.remove(0);​
 +        ​
 +        for (String animal : animals) {
 +            System.out.println(animal);​
 +        }
 +        ​
 +        Iterator iterator = animals.iterator();​
 +        while(iterator.hasNext()) {
 +            System.out.println(iterator.next());​
 +        }
 +        ​
 +        animals.clear(); ​
 +    }
 +}
 +</​code>​
   ​   ​
 ====Summary==== ====Summary====
Line 532: Line 601:
  
 ====Exerciții==== ====Exerciții====
 +
 +<note important>​
 +Veti încărca soluția voastră pe LambdaChecker,​ contest [[https://​beta.lambdachecker.io/​contest/​11 | POO - LAB3]]. ​
 +
 +Încercați să accesați de aici contest-ul, altfel e posibil să vă ceară o parolă care nu există. De asemena, să fiți logați pe LambdaChecker înainte de accesa link-ul. m(
 +</​note>​
 +Pentru acest laborator este de recomandat să creați un pachet numit ''​lab3'',​ unde veți face subpachete pentru task-uri.
  
 Gigel vrea să-i facă mamei sale un cadou de ziua ei și știe că-i plac foarte mult bomboanele. El are nevoie de ajutorul vostru pentru a construi cel mai frumos și gustos cadou: Gigel vrea să-i facă mamei sale un cadou de ziua ei și știe că-i plac foarte mult bomboanele. El are nevoie de ajutorul vostru pentru a construi cel mai frumos și gustos cadou:
Line 537: Line 613:
 **Task 1** [2p] **Task 1** [2p]
  
-Veți proiecta o clasă ​''​CandyBox''​, care va conține câmpurile private ​''​flavor'' ​(String) și ''​origin'' ​(String). Clasa va avea, de asemenea: +Veți proiecta o clasă CandyBox, care va conține câmpurile private flavor (String) și origin (String). ​ 
-                  * un constructor fără parametri + 
-                  * un constructor ​ce va inițializa ​toate câmpurile + 
-                  * o metodă de tip float ''​getVolume()''​, care va întoarce valoarea 0; +Clasa va avea, de asemenea: 
-                  Întrucât clasa ''​Object''​ se află în rădăcina arborelui de moștenire pentru orice clasă, orice instanță va avea acces la o serie de facilități oferite de Object. Una dintre ele este metoda ''​toString()'',​ al cărei scop este de a oferi o reprezentare unei instanțe sub forma unui șir de  caractere, utilizată în momentul apelului System.out.println(). Adăugați ​o metodă ​''​toString()''​, care va returna flavor-ul și regiunea de proveniență a cutiei de bomboane.+  * un constructor fără parametri ce va inițializa câmpurile ​cu "​sugar-free",​ respectiv "​Switzerland"​ 
 +  * un constructor cu parametri 
 +  ​* o metodă de tip float getVolume(),​ care va întoarce valoarea 0; 
 +  * o metodă toString(), care va returna flavor-ul și regiunea de proveniență a cutiei de bomboane ​("The [flavor] [origin] chocolate"​).
  
 **Task 2** [2p] **Task 2** [2p]
  
-Din ea derivați clasele ​''​Lindt''​''​Baravelli''​''​ChocAmor''​. Pentru un design interesant, cutiile vor avea forme diferite: +Din clasa CandyBox ​derivați clasele Lindt, Baravelli, ChocAmor. ​ 
-  * //Lindt// va conține ​''​length''​''​width''​''​height'' ​(float); + 
-  * //Baravelli// va fi un cilindru. Acesta va conține un câmp ''​radius'' ​și unul ''​height'' ​(float); +Pentru un design interesant, cutiile vor avea forme diferite: 
-  * //ChocAmor//, fiind un cub, va conține un camp ''​length'' ​(float);+  * Lindt va conține length, width, height (float); 
 +  * Baravelli va fi un cilindru. Acesta va conține un câmp radius și unul height (float); 
 +  * ChocAmor, fiind un cub, va conține un camp length (float).
  
 Clasele vor avea: Clasele vor avea:
-  * constructori fără parametri +  * constructori fără parametri ​ce vor initializa cu 0.0 campurile float; 
-  * constructori ​care permit inițializarea membrilor. ​Identificați o modalitate de reutilizare a codului existent. Pentru fiecare tip de cutie veți inițializa,​ în constructor,​ câmpurile ​''​flavor'' ​și ''​origin'' ​cu tipul corespunzător +  * constructori ​cu parametri (Identificați o modalitate de reutilizare a codului existent. Pentru fiecare tip de cutie veți inițializa,​ în constructor,​ câmpurile flavor și origin cu tipul corespunzător); 
-  * Suprascrieți metoda ​//getVolume()// pentru a întoarce volumul specific fiecărei cutii de bomboane, în funcție de tipul său. +  * Suprascrieți metoda getVolume() pentru a întoarce volumul specific fiecărei cutii de bomboane, în funcție de tipul său; 
-  * Suprascrieți ​ metoda ​//toString()// în clasele derivate, astfel încât aceasta să utilizeze implementarea metodei toString() din clasa de bază. Returnați un mesaj de forma //"The " + origin ​+ " " + flavor ​+ " ​has volume ​" + volume//;+  * Suprascrieți metoda toString() în clasele derivate, astfel încât aceasta să utilizeze implementarea metodei toString() din clasa de bază. Returnați un mesaj de forma "Lindt/Baravelli/Chocamor (*in functie de clasa de care apartine metoda): ​The [origin] [flavor] chocolate ​has volume ​[volume]".
  
 **Task 3** [1p] **Task 3** [1p]
    
  
-Adăugați o metodă ​''​equals()'' ​în clasa ''​CandyBox''​. Justificați criteriul de echivalentă ales. Vedeți metodele clasei [[https://​docs.oracle.com/​en/​java/​javase/​12/​docs/​api/​java.base/​java/​lang/​Object.html | Object]], moștenită de toate clasele - Object are metoda equals, a cărei implementare verifică echivalența obiectelor comparând referințele.+Adăugați o metodă equals() în clasa CandyBox. ​ 
 + 
 +Justificați criteriul de echivalentă ales.  
 + 
 +Creați obiecte de tip Lindt și testați egalitatea lor.
 <note important>​**Hint:​** <note important>​**Hint:​**
 Puteți genera automat metoda, cu ajutorul IDE. Selectați câmpurile considerate și Puteți genera automat metoda, cu ajutorul IDE. Selectați câmpurile considerate și
Line 566: Line 651:
 **Task 4** - //''​Upcasting''//​ [2p] **Task 4** - //''​Upcasting''//​ [2p]
  
-Acum că am stabilit tipul cutiilor de bomboane, putem construi ​cadoulrămânând la latitudinea vostră care va fi designul lui. În pachetul java.util se găsește clasa ''​ArrayList'',​ care definește un resizable array, cu metodele specifice (add, size, get, lista lor completa este în [[https://​docs.oracle.com/​en/​java/​javase/​12/​docs/​api/​java.base/​java/​util/​ArrayList.html|documentatie]]). Creați o clasă ''​CandyBag'',​ care va conține un ArrayList cu mai multe cutii din fiecare tip. Creați obiecte de tip Lindt și testați egalitatea lor;+Acum că am stabilit tipul cutiilor de bomboane, putem construi ​un cadou default care va contine in aceasta ordine: 
 +  * 3 cutii Lindt: Austria cherryAustria apricot , Austria strawberry, toate cu dimensiunile length 20, width 5.4, height 19.2 
 +  * o cutie Baravelli: Italy grape, radius 6.7, height 8.7 
 +  * 2 cutii ChocAmor: France coffee, France vanilla, ambele cu length 5.5  
 + 
 +Creați o clasă CandyBag, ​care va conține un ArrayList populat cu lista de mai sus. 
 + 
 + 
 +În pachetul java.util se găsește clasa ''​ArrayList'',​ care definește un resizable array, cu metodele specifice (add, size, get, lista lor completa este în [[https://​docs.oracle.com/​en/​java/​javase/​12/​docs/​api/​java.base/​java/​util/​ArrayList.html|documentatie]]). Creați o clasă ''​CandyBag'',​ care va conține un ArrayList cu mai multe cutii din fiecare tip.
  
  
 **Task 5** - //''​Downcasting''//​ [1p] **Task 5** - //''​Downcasting''//​ [1p]
  
-Adăugați clasei ​''​Baravelli''​, funcția ​''​printBaravelliDim()''​, care va afișa dimensiunile razei și înălțimii. În mod analog, procedați cu celelalte tipuri de cutii, adaugând metodele ​''​printChocAmorDim()'' ​și ''​printLindtDim()''​, în care să afișați dimensiunile fiecărei cutii.+Adăugați clasei Baravelli, funcția printBaravelliDim(),​ care va afișa dimensiunile razei și înălțimii. În mod analog, procedați cu celelalte tipuri de cutii, adaugând metodele printChocAmorDim() și printLindtDim(),​ în care să afișați dimensiunile fiecărei cutii.
  
 **Task 6** - //''​Agregare''//​ [2p] **Task 6** - //''​Agregare''//​ [2p]
  
-Gigel va vrea sa trimită prin curier cadoul, pentru a nu-l găsi mama lui mai devreme. Ajutați-l să determine locația, creând clasa  "​Area", care va conține un obiect de tip ''​CandyBag''​, un câmp "number" ​(int) și un câmp "street"​ (String)+Gigel va vrea sa trimită prin curier cadoul, pentru a nu-l găsi mama lui mai devreme. Ajutați-l să determine locația, creând clasa Area, care va conține un obiect de tip CandyBag, un câmp number” (int)un câmp street” (String) si un camp "​message" (String)
 Clasa va avea, de asemenea: Clasa va avea, de asemenea:
-  * un constructor fără parametri +  * un constructor fără parametri ​ce va initializa campurile cu 0, respectiv "​nowhere";​ 
-  * un constructor ​ce va inițializa toate câmpurile ​ +  * un constructor ​cu parametri. 
-  ​* ​Acum ca am finalizat construcția,​ îi vom oferi mamei informații despre cadoul ei printr-o felicitareCreați o metoda ​''​getBirthdayCard()''​, care va afișa, pe primul rand, adresa completă, iar apoi un mesaj de ''​la multi ani''​.  + 
-  * Tot aici, parcurgeți array-ul, apelând metoda ​''​toString()'' ​pentru elementele sale. +Acum ca am finalizat construcția,​ îi vom oferi mamei informații despre cadoul ei printr-o felicitare
-  ​* ​Parcurgeți array-ul și, folosind downcasting la clasa corespunzătoare,​ apelați metodele specifice fiecărei clase. Pentru a stabili tipul obiectului curent folosiți operatorul ​''​instanceof''​ +  * Creați o metoda getBirthdayCard(),​ care va afișa, pe primul rand, adresa completă, iar apoi un mesaj de la multi ani. 
-  ​* În final, modificați cum considerați programul anterior astfel încât să nu mai aveți nevoie de instanceof.+  * Tot aici, parcurgeți array-ul, apelând metoda toString() pentru elementele sale. 
 + 
 +Parcurgeți array-ul și, folosind downcasting la clasa corespunzătoare,​ apelați metodele specifice fiecărei clase. ​ 
 + 
 +Pentru a stabili tipul obiectului curent folosiți operatorul ​**instanceof**. 
 + 
 +<note important>​ 
 +În final, modificați cum considerați programul anterior astfel încât să nu mai aveți nevoie de instanceof ​(getBirtdayCardv2() method).</​note>​
  
 ==== Resurse ==== ==== Resurse ====
-/* {{:​poo-ca-cd:​laboratoare:​agregare-mostenire:​lab3-sol-2019.zip|Soluție}} */ 
   * [[:​poo-ca-cd:​laboratoare:​old-exercises#​agregare_si_mostenire|Exerciții din alți ani]]   * [[:​poo-ca-cd:​laboratoare:​old-exercises#​agregare_si_mostenire|Exerciții din alți ani]]
  
 ==== Referințe ==== ==== Referințe ====
- +  ​* [[https://​www.visual-paradigm.com/guide/​uml-unified-modeling-language/uml-class-diagram-tutorial/ | UML Diagrams]] 
-  ​* [[https://​www.journaldev.com/1325/composition-in-java-example/ | Composition Example]]+
   * [[https://​www.visual-paradigm.com/​guide/​uml-unified-modeling-language/​uml-aggregation-vs-composition/​ | Aggregation vs Composition]]   * [[https://​www.visual-paradigm.com/​guide/​uml-unified-modeling-language/​uml-aggregation-vs-composition/​ | Aggregation vs Composition]]
   * [[http://​docs.oracle.com/​javase/​tutorial/​java/​IandI/​subclasses.html | Inheritance JavaDoc]]   * [[http://​docs.oracle.com/​javase/​tutorial/​java/​IandI/​subclasses.html | Inheritance JavaDoc]]
 +  * [[https://​www.journaldev.com/​1775/​multiple-inheritance-in-java | Multiple Inheritance]]
   * [[http://​forum.codecall.net/​topic/​50451-upcasting-downcasting/​ | Upcasting and Downcasting]]   * [[http://​forum.codecall.net/​topic/​50451-upcasting-downcasting/​ | Upcasting and Downcasting]]
  
poo-ca-cd/laboratoare/agregare-mostenire.1601723178.txt.gz · Last modified: 2020/10/03 14:06 by radu_bogdan.pavel
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