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/19 15:15]
rares_stefan.epure [Cuvântul cheie super. Întrebuințări]
poo-ca-cd:laboratoare:agregare-mostenire [2023/10/22 21:29] (current)
alexandra.nioata [Exerciții]
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 526: Line 526:
 <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 ArrayList. ​Example====+====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>​
   ​   ​
 ====Summary==== ====Summary====
Line 533: Line 583:
   * 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 556: Line 606:
 ====Exerciții==== ====Exerciții====
  
-Gigel vrea să-i 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 șgustos cadou+<note important>​ 
-   +Veți încărca soluția voastră pe LambdaChecker,​ contest [[https://​beta.lambdachecker.io/​contest/​54/​problems?​page=1 | POO LAB3]].  
-**Task 1** [2p]+ 
 +Încercațsă accesațde aici contest-ul, altfel e posibil să vă ceară o parolă care nu existăDe asemena, să fițlogați pe LambdaChecker înainte de accesa link-ul. m( 
 +</​note>​ 
 +Schelet laborator[[https://​github.com/​oop-pub/​oop-labs/​tree/​master/​src/​lab3 | Laborator 3]] 
 + 
 + 
 +**Task 1** [1p] 
 + 
 +Veți proiecta o clasă Form care va avea câmpul privat color (String).
  
-Veți proiecta o clasă ''​CandyBox'',​ care va conține câmpurile private ''​flavor''​ (String) și ''​origin''​ (String). ​Clasa va avea, de asemenea: +Clasa va avea, de asemenea:  
-                  * un constructor fără parametri +   un constructor fără parametri, care va inițializa ​culoarea cu "​white";​ 
-                  * un constructor ce va inițializa ​toate câmpurile +   un constructor cu parametri;​ 
-                  * o metodă de tip float ''​getVolume()''​, care va întoarce valoarea 0; +  *  ​o metodă de tip float getArea(), 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.+  *  o metodă toString(): "This form has the color [color]"​.
  
 **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 Form derivați clasele ​SquareTriangleCircle 
-  * //​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)+  * clasa Triangle ​va avea 2 membri ​height ​și base de tip float; 
-  * //​ChocAmor//,​ fiind un cub, va conține un camp ''​length''​ (float);+  * clasa Circle ​va avea membrul ​radius ​de tip float; 
 +  * clasa Square ​va avea membrul side de tip 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 +  * constructori care permit inițializarea membrilor. Identificați o modalitate de reutilizare a codului existent; 
-  * Suprascrieți metoda ​//getVolume()// pentru a întoarce ​volumul ​specific fiecărei ​cutii de bomboane, în funcție de tipul său. +  * suprascrieți metoda ​getArea() pentru a întoarce ​aria specifică fiecărei ​figuri geometrice; 
-  * 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 baza.
  
-**Task 3** [1p]+**Task 3** [2p]
    
 +Adăugați o metodă equals() în clasa Triangle.
 +
 +Justificați criteriul de echivalență ales.
  
-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. 
 <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 589: Line 650:
 **Task 4** - //''​Upcasting''//​ [2p] **Task 4** - //''​Upcasting''//​ [2p]
  
-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.+Creați un vector ​de obiecte Form și populați-l cu obiecte de tip TriangleCircle ​și Square ​(upcasting). 
 +Parcurgeți acest vector și apelați metoda toString(pentru elementele saleCe observați
 + 
 +**Task 5** - //''​Downcasting''​// [2p]
  
 +Adăugați clasei Triangle metoda printTriangleDimensions,​ clasei Circle metoda printCircleDimensions și clasei Square metoda printSquareDimensions.
 +Implementarea metodelor constă în afișarea bazei și înălțimii,​ razei, respectiv laturii.
  
-**Task 5** - //''​Downcasting''//​ [1p]+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 și printSquareDimensions pentru Square). ​
  
-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.+Pentru ​stabili tipul obiectului curent folosiți operatorul instanceof.
  
-**Task 6** - //''​Agregare''//​ [2p]+**Task 6** - //''​Agregare''//​ [1p]
  
-Gigel va vrea sa trimită prin curier cadoul, pentru ​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) +Afișați dimensiunile formelor din vectorul creat fără a folosi operatorul instanceof.
-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.1632053724.txt.gz · Last modified: 2021/09/19 15:15 by rares_stefan.epure
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