Differences

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

Link to this comparison view

poo-ca-cd:laboratoare:agregare-mostenire [2021/09/12 12:29]
ioan_razvan.abagiu
poo-ca-cd:laboratoare:agregare-mostenire [2024/10/20 22:48] (current)
alexandra.nioata
Line 24: Line 24:
   * la **definirea** obiectului (înaintea constructorului:​ folosind fie o valoare inițială, fie blocuri de inițializare) ​   * la **definirea** obiectului (înaintea constructorului:​ folosind fie o valoare inițială, fie blocuri de inițializare) ​
   * în cadrul **constructorului** ​   * în cadrul **constructorului** ​
-  * chiar **înainte de folosire** (acest mecanism se numește inițializare leneșă (//lazy initialization//​))+  * chiar **înainte de folosire** (acest mecanism se numește inițializare leneșă (//lazy initialization//​)
  
 Exemple de cod: Exemple de cod:
Line 31: 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 40: 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 124: Line 124:
 ====Upcasting și Downcasting==== ====Upcasting și Downcasting====
  
-**Convertirea** unei referințe la o clasă derivată într-una a unei clase de bază poartă numele de **upcasting**. Upcasting-ul este facut **automat** și **nu** trebuie declarat explicit de către programator.+**Convertirea** unei referințe la o clasă derivată într-una a unei clase de bază poartă numele de **upcasting**. Upcasting-ul este făcut ​**automat** și **nu** trebuie declarat explicit de către programator.
  
 {{:​poo-ca-cd:​laboratoare:​agregare-mostenire:​upcast-downcast.png?​nolink&​400|}} {{:​poo-ca-cd:​laboratoare:​agregare-mostenire:​upcast-downcast.png?​nolink&​400|}}
Line 141: Line 141:
  
 // Obiectele Wind sunt instrumente // Obiectele Wind sunt instrumente
-// deoarece au aceeași interfață:​+// deoarece au ca și 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 183: 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 215: Line 215:
  
   ​   ​
-În liniile marcate cu **2** și **3** se execută un downcast de la ''​Animal''​ la ''​Wolf'',​ respectiv ''​Snake''​ pentru a putea fi apelate metodele specifice definite în aceste clase. Înaintea execuției downcast-ului (conversia de tip la Wolf respectiv Snake) verificăm dacă obiectul respectiv este de tipul dorit (utilizând operatorul ''​**instanceof**''​). Dacă am încerca să facem downcast către tipul ''​Wolf''​ al unui obiect ​instantiat ​la ''​Snake''​ mașina virtuală ar semnala acest lucru aruncând o excepție la rularea programului. ​+În liniile marcate cu **2** și **3** se execută un downcast de la ''​Animal''​ la ''​Wolf'',​ respectiv ''​Snake''​ pentru a putea fi apelate metodele specifice definite în aceste clase. Înaintea execuției downcast-ului (conversia de tip la Wolf respectiv Snake) verificăm dacă obiectul respectiv este de tipul dorit (utilizând operatorul ''​**instanceof**''​). Dacă am încerca să facem downcast către tipul ''​Wolf''​ al unui obiect ​instanțiat ​la ''​Snake''​ mașina virtuală ar semnala acest lucru aruncând o excepție la rularea programului. ​
   ​   ​
-Apelarea metodei ''​eat()''​ (linia **1**) se face direct, fără downcast, deoarece această metodă este definită și în clasa de bază ''​Animal''​. Datorită faptului că ''​Wolf''​ suprascrie (//​overrides//​) metoda ''​eat()'',​ apelul ''​a[0].eat()''​ va afișa "Wolf eating"​. Apelul ''​a[1].eat()''​ va apela metoda din clasă de bază (la ieșire va fi afișat "​Animal eating"​) deoarece ''​a[1]''​ este instantiat ​la ''​Snake'',​ iar ''​Snake''​ nu suprascrie metoda ''​eat()''​. ​+Apelarea metodei ''​eat()''​ (linia **1**) se face direct, fără downcast, deoarece această metodă este definită și în clasa de bază ''​Animal''​. Datorită faptului că ''​Wolf''​ suprascrie (//​overrides//​) metoda ''​eat()'',​ apelul ''​a[0].eat()''​ va afișa "Wolf eating"​. Apelul ''​a[1].eat()''​ va apela metoda din clasă de bază (la ieșire va fi afișat "​Animal eating"​) deoarece ''​a[1]''​ este instanțiat ​la ''​Snake'',​ iar ''​Snake''​ nu suprascrie metoda ''​eat()''​. ​
   ​   ​
 <note important>​Upcasting-ul este un element foarte important. De multe ori răspunsul la întrebarea:​ //este nevoie de moștenire?//​ este dat de răspunsul la întrebarea:​ //am nevoie de upcasting?//​ Aceasta deoarece upcasting-ul se face atunci când pentru unul sau mai multe obiecte din clase derivate se execută aceeași metodă definită în clasa părinte.</​note> ​ <note important>​Upcasting-ul este un element foarte important. De multe ori răspunsul la întrebarea:​ //este nevoie de moștenire?//​ este dat de răspunsul la întrebarea:​ //am nevoie de upcasting?//​ Aceasta deoarece upcasting-ul se face atunci când pentru unul sau mai multe obiecte din clase derivate se execută aceeași metodă definită în clasa părinte.</​note> ​
Line 223: Line 223:
 ===Să încercăm să evităm folosirea instanceof=== ===Să încercăm să evităm folosirea instanceof===
  
-Totuși, deși v-am ilustrat cum ''​instanceof''​ ne poate ajuta să ne dăm seama la ce să facem **downcasting**,​ este de preferat să ne organizăm clasele și designul codului în așa fel încât să lăsăm limbajul Java să facă automat verificarea tipului și să cheme metoda corespunzătoare. Vom refactororiza ​codul anterior pentru a nu fi nevoie de ''​instanceof'':​+Totuși, deși v-am ilustrat cum ''​instanceof''​ ne poate ajuta să ne dăm seama la ce să facem **downcasting**,​ este de preferat să ne organizăm clasele și designul codului în așa fel încât să lăsăm limbajul Java să facă automat verificarea tipului și să cheme metoda corespunzătoare. Vom refactoriza ​codul anterior pentru a nu fi nevoie de ''​instanceof'':​
  
 <code java5> <code java5>
Line 289: Line 289:
   * distruge designul orientat-obiect din perspectiva polimorfismului   * distruge designul orientat-obiect din perspectiva polimorfismului
   * încalcă [[https://​www.baeldung.com/​java-open-closed-principle|open-closed principle]]   * î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.+  * 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 ​10]] despre genericitate.
  
 **Soluții** pentru evitarea ''​instanceof'':​ **Soluții** pentru evitarea ''​instanceof'':​
Line 385: Line 385:
 <note warning>​Sintaxa Java permite apelarea metodelor statice pe instanțe (e.g. a.print în loc de Car.print), dar acest lucru este considerat bad practice pentru că poate îngreuna înțelegerea codului.</​note>​ <note warning>​Sintaxa Java permite apelarea metodelor statice pe instanțe (e.g. a.print în loc de Car.print), dar acest lucru este considerat bad practice pentru că poate îngreuna înțelegerea codului.</​note>​
  
-===Suprascrierea ​corecta ​a metodei equals(Object o)===+===Suprascrierea ​corectă ​a metodei equals(Object o)===
  
 Una din problemele cele mai des întâlnite este suprascrierea corectă a metodei //equals//. Mai jos putem vedea un exemplu de suprascriere incorectă a acestei metode. Una din problemele cele mai des întâlnite este suprascrierea corectă a metodei //equals//. Mai jos putem vedea un exemplu de suprascriere incorectă a acestei metode.
Line 408: Line 408:
 Car a = new Car(); Car a = new Car();
 Dacia b = new Dacia(); Dacia b = new Dacia();
-Int c = new Int(10);+int c = 10;
  
 a.equals(a);​ // afișează Car a.equals(a);​ // afișează Car
Line 415: Line 415:
 </​code>​ </​code>​
  
-Problema care se poate observa este că putem pasa ca argumente metodei equals si tipuri de date diferite de ''​Car'',​ lucru ce ar putea arunca excepții de cast sau când vrem să accesăm anumite proprietăți din instanță. Mai jos este modul corect de suprascrie metoda equals.+Problema care se poate observa este că putem pasa ca argumente metodei equals si tipuri de date diferite de ''​Car'',​ lucru ce ar putea arunca excepții de cast sau când vrem să accesăm anumite proprietăți din instanță. Mai jos este modul corect de suprascrie metoda equals.
  
 <code java> <code java>
Line 525: 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()''​ - modifică 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>​
 +
 +<note important>​
 +În exemplul de mai sus, la declararea unui ArrayList, se observă semnele "<>",​ utilizate pentru a specifica tipul de date al elementelor,​ pe care ArrayList le va conține. Acest lucru se numește genericitate și permite compilatorului să verifice în timpul compilării că se folosește tipul corect de date. Conceptul de genericitate se va studia mai mult în [[https://​ocw.cs.pub.ro/​courses/​poo-ca-cd/​laboratoare/​genericitate|laboratorul 10]] .
 +</​note>​
 +
 +==== Cuvântul-cheie "​final"​. Obiecte immutable ====
 +
 +Variabilele declarate cu atributul ''​final''​ pot fi inițializate **o singură dată**. Observăm că astfel unei variabile de tip referință care are atributul ''​final''​ îi poate fi asignată o singură valoare (variabila poate puncta către un singur obiect). O încercare nouă de asignare a unei astfel de variabile va avea ca efect generarea unei erori la compilare.
 +
 +Totuși, obiectul către care punctează o astfel de variabilă poate fi modificat intern, prin apeluri de metode sau acces la câmpuri.
 +
 +Exemplu: ​
 +
 +<code java5>
 +class Student {
 +
 +    private final Group group; ​                     // a student cannot change the group he was assigned in
 +    private static final int UNIVERSITY_CODE = 15;  // declaration of an int constant
 +
 +    public Student(Group group) {
 +        // reference initialization;​ any other attempt to initialize it will be an error
 +        this.group = group;
 +    }
 +}
 +</​code>​
 +
 +Dacă toate atributele unui obiect admit o unică inițializare,​ spunem că obiectul respectiv este ''​immutable'',​ în sensul că //nu putem schimba obiectul in sine (informația pe care o stochează, de exemplu), ci doar referința către un alt obiect.//. Exemple de astfel de obiecte sunt instanțele claselor ''​String''​ și ''​Integer''​. Odată create, prelucrările asupra lor (ex.: ''​toUpperCase()''​) se fac prin **instanțierea de noi obiecte** și nu prin alterarea obiectelor înseși.
 +
 +Exemplu:
 +
 +<code java5>
 +String s1 = "​abc";​
 +
 +String s2 = s1.toUpperCase(); ​ // s1 does not change; the method returns a reference to a new object which can be accessed using s2 variable
 +s1 = s1.toUpperCase(); ​        // s1 is now a reference to a new object
 +</​code>​
 +<note tip>
 +Observăm că în acest exemplu am folosit un String literal. Literalii sunt păstrați într-un ''​String pool''​ pentru a limita memoria utilizată. Asta înseamnă că dacă mai declarăm un alt literal "​abc",​ nu se va mai aloca memorie pentru încă un String, ci vom primi o referință către s-ul inițial. În cazul în care folosim constructorul pentru String, se alocă memorie pentru obiectul respectiv și primim o referință nouă.
 +Pentru a evidenția concret cum funcționează acest ''​String pool'',​ să luăm următorul exemplu:
 +</​note>​
 +<code java5>
 +String s1 = "​a"​ + "​bc";​
 +String s2 = "​ab"​ + "​c";​
 +</​code>​
 +În momentul în care compilatorul va încerca să aloce memorie pentru cele 2 obiecte, va observa că ele conțin, de fapt, aceeași informație. Prin urmare, va instanția un singur obiect, către care vor pointa ambele variabile, s1 și s2. Observați că această optimizare (de a reduce memoria) e posibilă datorită faptului că obiectele de tip String sunt **immutable**.
 +
 +O întrebare legitimă este, așadar, cum putem compara două String-uri (ținând cont de faptul că avem referințele către ele, cum am arătat mai sus). Să urmărim codul de mai jos:
 +
 +<code java5>
 +String a = "​abc";​
 +String b = "​abc";​
 +System.out.println(a == b);  // True
 +
 +String c = new String("​abc"​);​
 +String d = new String("​abc"​);​
 +System.out.println(c == d);  // False
 +</​code>​
 +
 +<note important>​
 +Operatorul <​nowiki>"​=="</​nowiki>​ compară //​referințele//​. Dacă am fi vrut să comparăm șirurile în sine am fi folosit metoda ''​equals''​. Același lucru este valabil și pentru oricare alt tip de referință:​ operatorul <​nowiki>"​=="</​nowiki>​ testează egalitatea //​referințelor//​ (i.e. dacă cei doi operanzi sunt de fapt același obiect).
 +
 +
 +Dacă vrem să testăm "​egalitatea"​ a două obiecte, se apelează metoda: ''​public boolean equals(Object obj)''​.
 +
 +Reţineţi semnătura acestei metode!
 +</​note>​
 +O consecință a faptului că obiectele de tip String sunt imutabile este determinată de faptul că efectuarea de modificări succesive conduce la crearea unui număr foarte mare de obiecte in String pool.
 +<code java5>
 +public static String concatenationUsingTheStringClass() {  ​
 +   ​String t = "​Java";  ​
 +   for (int i = 0; i < 10000; i++) {  ​
 +      t = t + "​POO";  ​
 +   ​}  ​
 +   ​return t;  ​
 +}  ​
 +</​code>​
 +În acest caz, numărul de obiecte create în memorie este unul foarte mare. Dintre acestea doar cel rezultat la final este util. Pentru a preveni alocarea nejustificată a obiectelor de tip String care reprezintă pași intermediari în obținerea șirului dorit putem alege să folosim clasa StringBuilder creată special pentru a efectua operații pe șiruri de caractere.
 +<code java5>
 +public static String concatenationUsingTheStringBuilderClass() {  ​
 +   ​StringBuilder sb = new StringBuilder("​Java"​);  ​
 +   for (int i = 0; i < 10000; i++) {  ​
 +        sb.append("​POO"​);  ​
 +   ​}  ​
 +   ​return sb.toString();  ​
 +}
 +</​code>​
 +
 +Cuvântul cheie final poate fi folosit și în alt context decât cel prezentat anterior. De exemplu, aplicat unei clase împiedică o eventuală derivare a acestei clase prin moștenire.
 +<code java5>
 +final class ParentClass {
 +}
 +
 +class ChildClass extends ParentClass {
 +    // compilation error, the class ParentClass cannot be extended
 +}
 +</​code>​
 +
 +În mod similar, în cazul în care aplicăm cuvântul cheie final unei metode, acest lucru împiedică o eventuală suprascriere a acelei metode.
 +<code java5>
 +class ParentClass {
 +   ​public final void dontOverride() {
 +        System.out.println("​You cannot override this method"​);​
 +   }
 +}
 +
 +class ChildClass extends ParentClass {
 +    public void dontOverride() {               // compilation error, the method dontOverride() from
 +        System.out.println("​But I want to!"​); ​ // the parent class cannot be overriden
 +    }
 +}
 +</​code>​
   ​   ​
 ====Summary==== ====Summary====
Line 531: Line 690:
   * Moștenire - **is a**   * Moștenire - **is a**
  
-**Upcasting** ​+**Upcasting:** 
   * convertire **copil** => **părinte**   * convertire **copil** => **părinte**
   * realizată automat   * realizată automat
  
-**Downcasting**+**Downcasting:**
   * convertire **părinte** =>​**copil**   * convertire **părinte** =>​**copil**
   * trebuie făcută explicit de către programator   * trebuie făcută explicit de către programator
   * încercați să evitați folosirea operatorului **instanceof**   * încercați să evitați folosirea operatorului **instanceof**
  
-**Suprascrierea** ​+**Suprascrierea:** 
   * înlocuirea funcționalității metodei din clasa de bază în clasa derivată   * înlocuirea funcționalității metodei din clasa de bază în clasa derivată
   * păstreaza numele și semnătura metodei   * păstreaza numele și semnătura metodei
  
-**Supraincărcarea**  ​+**Supraîncărcarea:**  ​
   * în interiorul clasei pot exista mai multe metode cu același nume, cu condiția ca semnătura (tipul, argumentele) să fie diferită   * în interiorul clasei pot exista mai multe metode cu același nume, cu condiția ca semnătura (tipul, argumentele) să fie diferită
  
-**super**+**Cuvântul cheie super:**
   * instanța clasei părinte   * instanța clasei părinte
   * amintiți-vă din laboratorul anterior că **[[:​poo-ca-cd:​laboratoare:​constructori-referinte#​cuvantul_cheie_this_intrebuintari|this]]** se referă la instanța clasei curente   * amintiți-vă din laboratorul anterior că **[[:​poo-ca-cd:​laboratoare:​constructori-referinte#​cuvantul_cheie_this_intrebuintari|this]]** se referă la instanța clasei curente
Line 554: Line 713:
 ====Exerciții==== ====Exerciții====
  
-Gigel vrea -facă mamei sale un cadou de ziua ei șștie că-i plac foarte mult bomboaneleEl are nevoie de ajutorul vostru pentru a construi cel mai frumos și gustos cadou: +<note important>​ 
-   +Pentru a încărca soluția, va trebui ​să accesațlink-ul https://​code.devmind.ro/​login,​ să intrațpe tab-ul Contests, unde vețgăsi laboratorul grupei voastre
-**Task 1** [2p]+ 
 +</​note>​ 
 + 
 +**Task 1 [1p]** 
 + 
 +Veți proiecta o clasă Form care va avea câmpul privat color (String). 
 + 
 +Clasa va avea, de asemenea: 
 + 
 + 
 +- un constructor fără parametri, care va inițializa culoarea cu “white”;​ 
 + 
 +- un constructor cu parametri;​ 
 + 
 +- o metodă de tip float getArea(), care va întoarce valoarea 0; 
 + 
 +- o metodă toString(): “This form has the color [color]”. 
 + 
 + 
 +**Task 2 [2p]** 
 + 
 +Din clasa Form derivați clasele Square, Triangle, Circle: 
 + 
 +- clasa Triangle (triunghi isoscel) va avea 2 membri height și base (adiacenta unghiurilor congruente) de tip float;
  
-Veți proiecta o clasă ''​CandyBox'',​ care va conține câmpurile private ''​flavor''​ (String) și ''​origin''​ (String). Clasa va avea, de asemenea: +- clasa Circle ​va avea membrul radius ​de tip float;
-                  * 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; +
-                  * Î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.+
  
-**Task 2** [2p]+- clasa Square va avea membrul side de tip float.
  
-Din ea derivați clasele ''​Lindt'',​ ''​Baravelli'',​ ''​ChocAmor''​. Pentru un design interesant, cutiile vor avea forme diferite: 
-  * //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;
-  * 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 +
-  * 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//;+
  
-**Task 3** [1p] +- constructori care permit inițializarea membrilor. Identificați o modalitate de reutilizare a codului existent;
- +
  
-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. Creați obiecte de tip Lindt și testați egalitatea lor. +- suprascrieți metoda getArea() pentru a întoarce aria specifică fiecărei figuri geometrice;
-<note important>​**Hint:​** +
-Puteți genera automat metoda, cu ajutorul IDE. Selectați câmpurile considerate și +
-analizați în ce fel va fi suprascrisă metoda equals.</​note>​+
  
-**Task 4** //''​Upcasting''//​ [2p]+suprascrieți metoda toString() în clasele derivate, astfel încât aceasta să utilizeze implementarea metodei toString() din clasa de baza.
  
-Acum că am stabilit tipul cutiilor de bomboane, putem construi cadoul, ră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. 
  
 +**Task 3 [2p]**
  
-**Task 5** - //''​Downcasting''//​ [1p]+Adăugați o metodă equals() în clasa Triangle.
  
-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.+Justificați criteriul ​de echivalență ales.
  
-**Task ​6** - //''​Agregare''// ​[2p]+Hint: Puteți genera automat metoda, cu ajutorul IDE. Selectați câmpurile considerate și analizați în ce fel va fi suprascrisă metoda equals. 
 + 
 +**Task ​4 - Upcasting [1p]** 
 + 
 +Creați un vector de obiecte Form și populați-l cu obiecte de tip Triangle, Circle și Square (upcasting).  
 + 
 +Parcurgeți acest vector și apelați metoda toString() pentru elementele sale. Ce observați?​ 
 + 
 +**Task 5 - Downcasting ​[2p]** 
 + 
 +Adăugați:​ 
 + 
 +- clasei Triangle metoda printTriangleDimensions,​ 
 + 
 +- clasei Circle metoda printCircleDimensions 
 + 
 +- clasei Square metoda printSquareDimensions 
 + 
 +Implementarea metodelor constă în afișarea bazei și înălțimii,​ razei, respectiv laturii. 
 + 
 + 
 +Parcurgeți vectorul de la exercițiul anterior și, folosind downcasting la clasa corespunzătoare,​ apelați metodele specifice fiecărei clase: 
 + 
 + 
 +- printTriangleDimensions pentru Triangle 
 + 
 +- printCircleDimensions pentru Circle 
 + 
 +- printSquareDimensions pentru Square 
 + 
 +Pentru a stabili tipul obiectului curent folosiți operatorul instanceof. 
 + 
 +**Task 6 - Agregare [1p]** 
 + 
 +Afișați dimensiunile formelor din vectorul creat fără a folosi operatorul instanceof. 
 + 
 +**Task 7 - Final [1p]** 
 + 
 +Afișați perimetrul fiecărui obiect din vectorul creat utilizând exclusiv funcția printPerimeter,​ modificând doar ce se afla in corpul funcției, lasând antetul identic.
  
-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) 
-Clasa va avea, de asemenea: 
-  * un constructor fără parametri 
-  * un constructor ce va inițializa toate câmpurile ​ 
-  * Acum ca am finalizat construcția,​ îi vom oferi mamei informații despre cadoul ei printr-o felicitare. Creaț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. 
-  * 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''​ 
-  * În final, modificați cum considerați programul anterior astfel încât să nu mai aveți nevoie de instanceof. 
  
 ==== Resurse ==== ==== Resurse ====
poo-ca-cd/laboratoare/agregare-mostenire.1631438980.txt.gz · Last modified: 2021/09/12 12:29 by ioan_razvan.abagiu
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