This shows you the differences between two versions of the page.
|
poo-ca-cd:laboratoare:abstractizare-clase-speciale-si-restrictii [2025/10/27 00:50] florian_luis.micu [Resurse și link-uri utile] |
poo-ca-cd:laboratoare:abstractizare-clase-speciale-si-restrictii [2025/11/12 11:31] (current) florian_luis.micu [Clase și metode abstracte] |
||
|---|---|---|---|
| Line 3: | Line 3: | ||
| * Autori: [[miculuis1@gmail.com | Florian-Luis Micu ]], [[sorinabuf@gmail.com | Sorina-Anamaria Buf ]], [[stefancocioran@gmail.com | Ștefan Cocioran ]] | * Autori: [[miculuis1@gmail.com | Florian-Luis Micu ]], [[sorinabuf@gmail.com | Sorina-Anamaria Buf ]], [[stefancocioran@gmail.com | Ștefan Cocioran ]] | ||
| * Data publicării: 27.10.2025 | * Data publicării: 27.10.2025 | ||
| - | * Data ultimei modificări: 27.10.2025 | + | * Data ultimei modificări: 04.11.2025 |
| + | * clarificări și expandarea conținutului despre DTO-uri. | ||
| + | * ștergerea notiței legată de contest (numele problemei a fost actualizat pe Code Devmind). | ||
| =====Obiective===== | =====Obiective===== | ||
| Line 10: | Line 13: | ||
| Aspectele urmărite sunt: | Aspectele urmărite sunt: | ||
| - | * înțelegerea conceptelor de agregare și compunere. | + | * înțelegerea abstractizării și a modului în care ascunde detaliile interne. |
| - | * utilizarea corectă a moștenirii pentru refolosirea codului. | + | * utilizarea corectă a claselor abstracte și interfețelor pentru refolosirea și organizarea codului. |
| - | * înțelegerea diferenței între moștenire și agregare. | + | * înțelegerea diferenței dintre clase normale, abstracte și interfețe. |
| - | * exersarea conversiilor upcasting și downcasting. | + | * exersarea implementării metodelor abstracte și default. |
| - | * implementarea polimorfismului în Java. | + | * înțelegerea și utilizarea polimorfismului în Java. |
| - | * diferența dintre overriding și overloading. | + | * folosirea obiectelor imutabile pentru cod sigur și clar. |
| - | * întrebuințarea cuvântului cheie super. | + | * aplicarea constantelor cu final pentru valori fixe. |
| Aspectele **bonus** urmărite sunt: | Aspectele **bonus** urmărite sunt: | ||
| * Problema diamantului pentru metode default în interfețe. | * Problema diamantului pentru metode default în interfețe. | ||
| - | * Clase de tip Record. | + | * clase de tip Record. |
| - | * Clase de tip Enum. | + | * clase de tip Enum. |
| <note warning> | <note warning> | ||
| Line 32: | Line 35: | ||
| Abstractizarea este unul dintre cele 4 principii POO de bază (**Abstractizare, Încapsulare, Moștenire, Polimorfism**). | Abstractizarea este unul dintre cele 4 principii POO de bază (**Abstractizare, Încapsulare, Moștenire, Polimorfism**). | ||
| - | Acest principiu este folosit pentru a ascunde detaliile interne ale obiectelor și evidențiază doar comportamentele esențiale. Ea oferă un șablon comun pentru o categorie de obiecte, fără a specifica implementarea fiecăruia. În Java, abstractizarea este realizată prin clase abstracte și interfețe. | + | Acest principiu este folosit pentru a ascunde detaliile interne ale obiectelor și evidențiază doar comportamentele esențiale. Ea oferă un **șablon comun** pentru o categorie de obiecte, fără a specifica implementarea fiecăruia. În Java, abstractizarea este realizată prin **clase abstracte** și **interfețe**. |
| ====Clase și metode abstracte==== | ====Clase și metode abstracte==== | ||
| - | Programarea orientată pe obiecte permite modelarea unor concepte generale care pot avea comportamente variate în funcție de implementare. Clasele și metodele abstracte oferă un mecanism esențial pentru proiectarea ierarhiilor de clase flexibile și extensibile. | + | Programarea orientată pe obiecte permite modelarea unor concepte generale care pot avea comportamente variate în funcție de implementare. Clasele și metodele abstracte oferă un mecanism esențial pentru proiectarea ierarhiilor de clase **flexibile** și **extensibile**. |
| ===Ce este o metodă abstractă?=== | ===Ce este o metodă abstractă?=== | ||
| Line 84: | Line 87: | ||
| <note important> | <note important> | ||
| - | Este important să înțelegem că dacă avem cel puțion o metodă abstractă, trebuie să declarăm și clasa acesteia ca fiind abstractă. | + | Este important să înțelegem că dacă avem **cel puțin o metodă abstractă**, trebuie să declarăm și clasa acesteia ca fiind abstractă. |
| </note> | </note> | ||
| Line 95: | Line 98: | ||
| O clasă abstractă, **nu poate fi instanțiată direct**, trebuie moștenită de o altă clasă folosind keyword-ul ''extends''. | O clasă abstractă, **nu poate fi instanțiată direct**, trebuie moștenită de o altă clasă folosind keyword-ul ''extends''. | ||
| - | Acest mecanism funcționează și pe lanțuri de moștenire între clase abstracte: o clasă abstractă poate moșteni o altă clasă abstractă și poate adăuga metode abstracte noi. Toate metodele abstracte din lanț trebuie să fie implementate în cele din urmă într-o clasă concretă pentru a putea crea obiecte. | + | Acest mecanism funcționează și pe **lanțuri de moștenire** între clase abstracte: o clasă abstractă poate moșteni o altă clasă abstractă și poate adăuga metode abstracte noi. Toate metodele abstracte din lanț **trebuie să fie implementate** în cele din urmă într-o clasă concretă pentru a putea crea obiecte. |
| <code java Vehicle.java> | <code java Vehicle.java> | ||
| Line 148: | Line 151: | ||
| <code java> | <code java> | ||
| - | Vehicle vehicle = new Sedan(); | + | Sedan sedan = new Sedan(); |
| - | vehicle.startEngine(); // Output: Car engine started! | + | sedan.startEngine(); // Output: Car engine started! |
| - | vehicle.openTrunk(); // Output: Trunk opened in the back of the car! | + | sedan.openTrunk(); // Output: Trunk opened in the back of the car! |
| </code> | </code> | ||
| <note important> | <note important> | ||
| - | * Clasa ''Vehicle'' și clasa ''Car'' nu pot fi instanțiate, deoarece nu implementează toate metodele abstracte moștenite și proprii. | + | * Clasa ''Vehicle'' și clasa ''Car'' nu pot fi instanțiate, deoarece **nu implementează** toate metodele abstracte moștenite și proprii. |
| - | * Dacă dorim să nu se poată instanția clasa ''Animal'' de mai sus, am putea să o declarăm ca fiind abstractă chiar dacă aceasta nu ar avea metode abstracte:<code java> | + | * Dacă dorim să nu se poată instanția clasa ''Animal'' de mai sus, am putea să o declarăm ca fiind abstractă chiar dacă aceasta **nu** ar avea metode abstracte:<code java> |
| public abstract class Animal { // valid | public abstract class Animal { // valid | ||
| private double weight; | private double weight; | ||
| Line 171: | Line 174: | ||
| <note tip> | <note tip> | ||
| - | * O clasă abstractă nu poate fi instanțiată, deoarece o clasă abstractă poate conține metode abstracte care nu au încă o implementare. Chiar și dacă clasa nu conține metode abstracte această restricție este păstrată pentru a putea exista scenariul de mai sus. | + | * O clasă abstractă nu poate fi instanțiată, deoarece o clasă abstractă **poate** conține metode abstracte care nu au încă o implementare. Chiar și dacă clasa **nu** conține metode abstracte această restricție este păstrată pentru a putea exista scenariul de mai sus. |
| - | * O clasă abstractă poate avea constructori chiar dacă nu poate fi instanțiată direct, deoarece acei constructori pot fi folosiți la inițializarea stării interne a clasei, ca în exemplul de mai sus. | + | * O clasă abstractă poate avea constructori chiar dacă nu poate fi instanțiată direct, deoarece acei constructori pot fi folosiți la **inițializarea stării interne** a clasei, ca în exemplul de mai sus. |
| </note> | </note> | ||
| Line 197: | Line 200: | ||
| ====Interfețe==== | ====Interfețe==== | ||
| - | Interfețele oferă un mecanism prin care putem defini **comportamente** fără a impune moștenire de implementare. Ele stabilesc un contract pe care orice clasă îl poate îndeplini, indiferent din ce parte a ierarhiei de clase provine. | + | Interfețele oferă un mecanism prin care putem defini **comportamente** fără a forța clasele să moștenească implementarea. Ele stabilesc un contract pe care orice clasă îl poate îndeplini, indiferent din ce parte a ierarhiei de clase provine. |
| ===Ce este o interfață?=== | ===Ce este o interfață?=== | ||
| Line 271: | Line 274: | ||
| ===Iniţializarea câmpurilor în interfeţe=== | ===Iniţializarea câmpurilor în interfeţe=== | ||
| - | În interfețe toate câmpurile sunt implicit ''public static final''. Nu pot exista **blank final**s (câmpuri finale neinițializate), dar pot exista constante non-primitive dacă sunt inițializate la declarație. | + | În interfețe toate câmpurile sunt implicit ''public static final''. Nu pot exista **blank finals** (câmpuri finale neinițializate), dar pot exista **constante non-primitive** dacă sunt inițializate la declarație. |
| <code java> | <code java> | ||
| Line 281: | Line 284: | ||
| ===Interfețele ca tipuri=== | ===Interfețele ca tipuri=== | ||
| - | După ce definim o interfață, ea devine un tip de referință în Java, la fel ca o clasă. Asta înseamnă că putem: | + | După ce definim o interfață, ea devine un **tip de referință** în Java, la fel ca o clasă. Asta înseamnă că putem: |
| * Declara variabile de tipul interfeței | * Declara variabile de tipul interfeței | ||
| * Folosi interfața ca tip pentru parametrii unor metode | * Folosi interfața ca tip pentru parametrii unor metode | ||
| * Specifica interfața ca tip de return al unei metode | * Specifica interfața ca tip de return al unei metode | ||
| - | Astfel, orice obiect care implementează interfața poate fi atribuit unei variabile de acel tip, indiferent de clasa sa concretă. | + | Astfel, orice obiect care implementează interfața poate fi atribuit unei variabile de acel tip, indiferent de clasa sa concretă (upcasting). |
| <code java> | <code java> | ||
| Line 334: | Line 337: | ||
| ===Moștenire multiplă=== | ===Moștenire multiplă=== | ||
| - | În Java, o interfață poate moșteni mai multe interfețe folosind keyword-ul extends. Aceasta permite combinarea comportamentelor din mai multe surse fără a fi nevoie de moștenire multiplă de clase (care nu este permisă în Java). | + | În Java, **o interfață** poate moșteni **mai multe interfețe** folosind keyword-ul ''extends''. Acesta permite combinarea comportamentelor din mai multe surse fără a fi nevoie de moștenire multiplă de clase (care nu este permisă în Java). |
| <code java> | <code java> | ||
| Line 357: | Line 360: | ||
| </code> | </code> | ||
| - | Totodată, o clasă poate moșteni mai multe interfețe folosind keyword-ul ''implements'': | + | Totodată, **o clasă** poate moșteni **mai multe interfețe** folosind keyword-ul ''implements'': |
| <code java> | <code java> | ||
| Line 412: | Line 415: | ||
| </code> | </code> | ||
| - | <note tip>Situația de mai sus **nu** reprezintă //Problema diamantului//, deoarece chiar dacă se pot moșteni mai multe interfețe, acestea nu au un corp, deci implementarea este lăsată la latitudinea clasei care le va implementa.</note> | + | <note tip>Situația de mai sus **nu** se încadrează la //Problema diamantului//, deoarece chiar dacă se pot moșteni mai multe interfețe, acestea nu au un corp, deci implementarea este lăsată la latitudinea clasei care le va implementa.</note> |
| <spoiler [Optional] Metode default în interfețe și Problema diamantului> | <spoiler [Optional] Metode default în interfețe și Problema diamantului> | ||
| **Metode default în interfețe** | **Metode default în interfețe** | ||
| - | În Java (de la Java 8), interfețele pot avea metode cu implementare folosind cuvântul cheie ''default''. | + | În Java (de la Java 8), interfețele pot avea **metode cu implementare** folosind cuvântul cheie ''default''. |
| Scopul lor: | Scopul lor: | ||
| Line 479: | Line 482: | ||
| ====Clase abstracte vs. Interfețe==== | ====Clase abstracte vs. Interfețe==== | ||
| - | După cum se poate observa, atât clasele abstracte cât și interfețele oferă avantaje similare. Pentru a observa asemănările și diferențele dintre acestea am creat următorul tabel: | + | După cum se poate observa, atât clasele abstracte cât și interfețele oferă avantaje similare. Să observăm următorul tabel pentru o comparație directă: |
| ^ Caracteristică ^ Clasă abstractă ^ Interfață ^ | ^ Caracteristică ^ Clasă abstractă ^ Interfață ^ | ||
| Line 494: | Line 497: | ||
| ====Exemplu ierarhie de clase==== | ====Exemplu ierarhie de clase==== | ||
| - | Proiectele voastre ar trebui să conțină o combinație între clase abstracte și interfețe. | + | Un proiect complex ar trebui să conțină o **combinație** între clase abstracte și interfețe. |
| - | Să presupunem următoarea ierarhie de clase. | + | Să presupunem următoarea ierarhie de clase: |
| {{:poo-ca-cd:laboratoare:abstractizare-clase-speciale-si-restrictii:inheritance_example.png?nolink&600|}} | {{:poo-ca-cd:laboratoare:abstractizare-clase-speciale-si-restrictii:inheritance_example.png?nolink&600|}} | ||
| Line 539: | Line 542: | ||
| } | } | ||
| </code> | </code> | ||
| + | |||
| + | <note tip> | ||
| + | Conform laboratoarelor trecute, vă reamintim că puteți crea de asemenea și **constante globale** dacă faceți un câmp ''static final''. | ||
| + | </note> | ||
| De asemenea, putem marca **parametrii** unei metode ca fiind ''final'' pentru a indica faptul că aceștia **nu pot fi schimbați în corpul unei metode**: | De asemenea, putem marca **parametrii** unei metode ca fiind ''final'' pentru a indica faptul că aceștia **nu pot fi schimbați în corpul unei metode**: | ||
| Line 654: | Line 661: | ||
| ====Enums==== | ====Enums==== | ||
| - | Enums sunt tipuri speciale de clasă care definesc un set fix de constante. Ele oferă o modalitate sigură și lizibilă de a reprezenta valori finite și constante într-un program. | + | Enums sunt tipuri speciale de clasă care definesc un **set fix de constante**. Ele oferă o modalitate **sigură** și **lizibilă** de a reprezenta **valori finite** și **constante** într-un program. |
| Exemplu simplu: | Exemplu simplu: | ||
| Line 762: | Line 769: | ||
| ===Avantaje ale folosirii Enum=== | ===Avantaje ale folosirii Enum=== | ||
| - | * Cod mai clar și mai lizibil comparativ cu constantele int sau String. | + | * Cod mai clar și mai lizibil comparativ cu constantele de tip ''int'' sau ''String''. |
| - | * Siguranță la compilare: nu poți atribui valori invalide. | + | * Siguranță la compilare, deoarece nu putem atribui valori invalide. |
| - | * Poți adăuga metode și comportamente specifice fiecărei constante. | + | * Putem adăuga metode și comportamente specifice fiecărei constante. |
| * Se integrează bine cu switch/case pentru decizii pe valori finite. | * Se integrează bine cu switch/case pentru decizii pe valori finite. | ||
| <note tip> | <note tip> | ||
| - | Puteți folosi în continuare câmpuri de tipul ''static final'' într-o clasă normală care are rol de a ține constante, însă este de preferat să folosiți Enum-uri fiind o alternativă mai modernă. | + | Puteți folosi în continuare câmpuri de tipul ''static final'' într-o clasă normală care are rol de a ține constante, însă este de **preferat** să folosiți Enum-uri fiind o alternativă mai modernă cu toate avantajele de mai sus. |
| </note> | </note> | ||
| Line 828: | Line 835: | ||
| <note tip> | <note tip> | ||
| - | Observă că getteri există, dar nu se numesc ''getName()'', ci exact ca proprietatea: ''name()''. | + | Observați că getteri există, dar nu se numesc ''getName()'', ci exact ca proprietatea definită în clasă (ex. ''name()''). |
| </note> | </note> | ||
| Line 889: | Line 896: | ||
| <note tip> | <note tip> | ||
| - | * DTO (Data Transfer Object) este un obiect folosit pentru **transportul datelor** între straturi ale unei aplicații sau între aplicații diferite, **fără logică de business**. De exemplu, dacă am vrea să transmitem tot obiectul ''User'' dintr-o aplicație bancară am putea transmite inclusiv date confidențiale despre acesta (CNP, adresă etc.). Pentru a transmite doar datele necesare, putem crea o clasă ''UserDTO'' care conține doar câmpurile relevante pentru transfer. | + | Veți învăța despre **Spring** când veți face web back-end development. |
| - | * Veți învăța despre **Spring** când veți face web back-end development. | + | </note> |
| + | |||
| + | ===Ce sunt DTO-urile?=== | ||
| + | |||
| + | **DTO (Data Transfer Object)** este un obiect folosit pentru a **transfera** date între diferite părți ale unei aplicații sau între aplicații, **fără a conține logică de business**. Scopul lui este să transporte doar informațiile necesare, într-o formă **sigură** și **optimă**. | ||
| + | |||
| + | De exemplu, într-o aplicație bancară avem clasa User, care ar putea conține informații sensibile precum: | ||
| + | * nume | ||
| + | |||
| + | * CNP | ||
| + | * adresă | ||
| + | * sold cont | ||
| + | * roluri etc. | ||
| + | |||
| + | Dacă vrem să trimitem date despre utilizator către interfața web sau către alt serviciu, nu vrem să expunem date confidențiale precum CNP-ul sau adresa completă. În acest caz, creăm un ''UserDTO'', o clasă separată care conține **doar** informațiile necesare transferului, de exemplu: | ||
| + | |||
| + | <code java UserDTO.java> | ||
| + | public class UserDTO { | ||
| + | private String name; | ||
| + | private String email; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Astfel: | ||
| + | * Protejăm datele sensibile | ||
| + | * Controlăm ce date sunt trimise | ||
| + | * Simplificăm transferul de date | ||
| + | * Evităm expunerea logicii interne a aplicației | ||
| + | |||
| + | ==Conversia dintr-o clasă în DTO== | ||
| + | |||
| + | Ca să convertim un obiect dintr-o clasă normală (**model/entity**) într-un **DTO**, există mai multe abordări. În principiu luăm doar câmpurile de care avem nevoie și le copiem în obiectul DTO. | ||
| + | |||
| + | Există mai multe metode pentru a face această copiere, însă cea recomandată este prin folosirea unui constructor: | ||
| + | |||
| + | <code java> | ||
| + | public class UserDTO { | ||
| + | private String name; | ||
| + | private String email; | ||
| + | |||
| + | public UserDTO(User user) { | ||
| + | this.name = user.getName(); | ||
| + | this.email = user.getEmail(); | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Totodată, puteți rescrie codul de mai sus folosind ''record'' astfel: | ||
| + | |||
| + | <code java> | ||
| + | public record UserDTO(String name, String email) {} | ||
| + | </code> | ||
| + | |||
| + | <note tip> | ||
| + | * Când veți începe să lucrați cu framework-ul **Spring/Spring Boot**, veți întâlni termenii **model** sau **entity**, care reprezintă de obicei **obiectele stocate în baza de date**. Pentru moment este suficient să rețineți că aceste clase descriu obiecte reale din aplicație, cu **atribute** și **comportament**. | ||
| + | * În laboratoarele următoare vom învăța despre **Builder**, fiind un alt concept care ne poate ajuta în crearea DTO-urilor. | ||
| </note> | </note> | ||
| =====Summary===== | =====Summary===== | ||
| - | **Relații între obiecte:** | + | **Abstractizare** |
| - | * Agregare - **has a** | + | * Permite ascunderea detaliilor interne și expunerea doar a comportamentului esențial. |
| - | * Moștenire - **is a** | + | * Realizată prin **clase abstracte** și **interfețe**. |
| + | * Favorizează **polimorfismul** și **reutilizarea codului**. | ||
| - | **Upcasting:** | + | **Clase abstracte** |
| - | * convertire **copil** => **părinte** | + | * Pot conține metode **abstracte** și metode cu implementare. |
| - | * realizată automat | + | * Pot avea **câmpuri și constructori**. |
| + | * **Nu pot fi instanțiate** direct. | ||
| + | * Forțează subclasele să implementeze metodele abstracte. | ||
| + | * Permite moștenire între clase abstracte. | ||
| - | **Downcasting:** | + | **Interfețe** |
| - | * convertire **părinte** =>**copil** | + | * Definește un **contract** de comportamente (metode abstracte). |
| - | * trebuie făcută explicit de către programator | + | * Poate conține metode **default** (cu implementare) și **static**. |
| - | * încercați să evitați folosirea operatorului **instanceof** | + | * Permite **moștenire multiplă** fără conflicte de ierarhie (exceptând problema diamantului). |
| + | * Polimorfism: o variabilă de tip interfață poate referi orice clasă care o implementează. | ||
| + | * Nu poate avea constructori. | ||
| + | * Toate câmpurile sunt **implicit public static final**. | ||
| - | **Suprascrierea:** | + | **Problema diamantului (în interfețe)** |
| - | * înlocuirea funcționalității metodei din clasa de bază în clasa derivată | + | * Apare când o clasă implementează **două interfețe** cu aceeași metodă default. |
| - | * păstreaza numele și semnătura metodei | + | * Soluția: clasa trebuie să **suprascrie metoda** și să aleagă implementarea. |
| + | |||
| + | **Constante (final)** | ||
| + | * Variabilele final nu pot fi modificate după inițializare. | ||
| + | * Folosite pentru **constante globale**, **valoare fixă în clase** sau **enum-uri**. | ||
| + | * În interfețe, toate câmpurile sunt **implicit public static final**. | ||
| + | |||
| + | **Obiecte imutabile** | ||
| + | * Obiectele nu își pot schimba starea după creare. | ||
| + | * Se obțin prin câmpuri private final și **fără setteri**. | ||
| + | * Oferă **siguranță în programarea concurentă**. | ||
| + | |||
| + | **Enums** | ||
| + | * Tip special care reprezintă un set fix de constante. | ||
| + | * Fiecare constantă este de fapt un **obiect de tip enum**. | ||
| + | * Pot avea **câmpuri, constructori și metode**. | ||
| + | * Metode utile: .values(), .ordinal(), .name(). | ||
| + | |||
| + | **Records** | ||
| + | * Introduse în Java 16, pentru **tipuri de date imutabile**. | ||
| + | * Au câmpuri finale, constructor generat automat, equals(), hashCode() și toString(). | ||
| + | * Perfect pentru **DTO-uri** sau obiecte care transportă date fără logică suplimentară. | ||
| - | **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ă | ||
| - | **Cuvântul cheie super:** | ||
| - | * instanța clasei părinte | ||
| - | * amintiți-vă din laboratorul anterior că ''this'' se referă la instanța clasei curente | ||
| =====Exerciții===== | =====Exerciții===== | ||
| Line 923: | Line 1008: | ||
| * Exercițiile vor fi făcute pe platforma [[https://code.devmind.ro/|Devmind Code]]. Găsiți exercițiile din acest laborator în **contestul aferent**. | * Exercițiile vor fi făcute pe platforma [[https://code.devmind.ro/|Devmind Code]]. Găsiți exercițiile din acest laborator în **contestul aferent**. | ||
| * Vă recomandăm să copiați scheletul și să faceți exercițiile **mai întâi** în IntelliJ, deoarece acolo aveți acces la o serie de **instrumente** specifice unui IDE. După ce ați terminat exercițiile puteți să le **copiați** pe Devmind Code. | * Vă recomandăm să copiați scheletul și să faceți exercițiile **mai întâi** în IntelliJ, deoarece acolo aveți acces la o serie de **instrumente** specifice unui IDE. După ce ați terminat exercițiile puteți să le **copiați** pe Devmind Code. | ||
| + | </note> | ||
| + | |||
| + | <note note> | ||
| + | În contest veți observa că problema se cheamă //Problem-LAB05-POO//, însă nu este o problemă. Vom redenumi problema cât de curând. | ||
| </note> | </note> | ||
| Line 932: | Line 1021: | ||
| * Un task (''CounterOutTask.java'') care incrementeaza un contor global și afișează valoarea contorului după fiecare incrementare. | * Un task (''CounterOutTask.java'') care incrementeaza un contor global și afișează valoarea contorului după fiecare incrementare. | ||
| - | <note>**Notă**: Acesta este un exemplu simplu pentru [[http://en.wikipedia.org/wiki/Command_pattern|Command Pattern]]</note> | + | <note>**Notă**: Acesta este un exemplu simplu pentru Design Pattern-ul [[http://en.wikipedia.org/wiki/Command_pattern|Command Pattern]], despre care vom învăța în următoarele laboratoare.</note> |
| {{:poo-ca-cd:laboratoare:clase-abstracte-interfete:ex1.png?600|}} | {{:poo-ca-cd:laboratoare:clase-abstracte-interfete:ex1.png?600|}} | ||