Se afișează postările cu eticheta java. Afișați toate postările
Se afișează postările cu eticheta java. Afișați toate postările

miercuri, 1 aprilie 2026

Clase și metode abstracte set de probleme

Aceste probleme se vor realiza în baza noțiunilor studiate la instruirea teoretică:  https://musteatadidactic.blogspot.com/2026/03/clase-si-metode-abstracte.html


1. Deschideți editorul de cod Java și rulați Exemplul 1 din partea teoretică. Apoi realizați următoarele modificări:
a. Adăugați clasei Figura metoda: static void afisare(String autor) care va afișa autorul programului.     Testați metoda în main().
b. Adăugați o nouă subclasă pentru clasa Figura. Instanțiați subclasa în main().

2. Se cere realizarea unei aplicații Java care să simuleze funcționarea unor aplicații digitale populare (rețele sociale, platforme educaționale, servicii de streaming).
a. Creați clasa abstractă Aplicatie, care va conține:
- atributul nume (de tip String);
- un constructor cu parametri pentru inițializarea atributului;
- metoda concretă afisareNume(), care afișează denumirea aplicației;
- metodele abstracte: login(), logout() și functionalitatePrincipala()
b. Creați cel puțin 3 clase care extind clasa Aplicatie:
- AplicatieSocialMedia (ex.: Instagram, Facebook) în care supradefiniți:
metoda login() va afișa: „Utilizatorul s-a autentificat în aplicația X”
metoda functionalitatePrincipala() va afișa: „Postează o imagine”
- AplicatieEducatie (ex.: platformă e-learning) în care supradefiniți:
metoda login() va afișa: „Utilizatorul s-a autentificat în aplicația X”
metoda functionalitatePrincipala() va afișa: „Accesează un curs”
- AplicatieStreaming (ex.: video sau muzică)
metoda login() va afișa: „Utilizatorul s-a autentificat în aplicația X”
metoda functionalitatePrincipala() va afișa: „Redă un videoclip”
c. Testarea în metoda main
- creați un array de tip Aplicatie;
- adăugați obiecte din toate cele trei tipuri de aplicații;
- parcurgeți array-ul și apelați metodele definite.

3. Efectuați următoarele acțiuni:

a) Având dată următoarea clasă abstractă. Transcrieți această clasă în editorul de cod Java:

abstract class Policeman {
private String nume;
private String prenume;
private int staj;
public Policeman(String n, String p,int s) {
nume = n;
prenume = p;
staj = s;
}
public String getNume() {
return nume; 
}
public String getPrenume() {
return prenume; 
}
public int getStaj() {
return staj; 
}
public abstract double venit();
public abstract int rang();
}

Vor urma 3 clase: Soldat din care se va deriva Sergent din care mai apoi se va deriva Locotenent. Metodele abstracte venit() și rang() vor fi implementate în clase. Metoda rang() va returna rangul omului legii. Va începe de la 1 pentru soldat, va urma 2 pentru sergent și 3 pentru locotenent.
b) Elaborați clasa Soldat pornind de la următorul codul sursă:

class Soldat extends Policeman {
protected static double plataBazaSoldat = 3600;
Soldat(String nume, String prenume, int staj) {
super(nume, prenume, staj);
}
public double getPlataSoldat(){
}
}

Plata de bază pentru un soldat este 3600 lei pe lună. Salariul net constituie 85% din salariul de bază + 6% din rădăcina pătrată din plata de bază înmulțit la staj. Rangul său este 1.
c) Elaborați clasa Sergent pornind de la următorul codul sursă:

class Sergent extends Soldat {
protected static double plataBazaSerjant = 4700;
public Sergent(String nume, String prenume, int staj) {
super(nume, prenume, staj); 
}
}

Plata de bază pentru un sergent este 4700 lei pe lună. Salariul net constituie 82% din salariul de bază + 1.2 înmulțit la rădăcina pătrată din plata de bază înmulțit la staj. Rangul său este de 2 ori mai mare decât rangul soldatului care trebuie obținut cu ajutorul variabilei predefinite super.

d) Elaborați clasa Locotenent pornind de la următorul codul sursă:

class Locotenent extends Serjant{
protected static double plataBazaLocotenent = 5900;
public Locotenent(String nume, String prenume, int staj) {
super(nume, prenume, staj);
}
}

Plata de bază pentru un locotenent este 5900 lei pe lună. Salariul net constituie 80% din salariul de bază + 1.3 înmulțit la rădăcina pătrată din plata de bază înmulțit la staj. Rangul său este cu o unitate mai mare decât rangul locotenentului care trebuie obținut, de asemenea, cu ajutorul variabilei predefinite super.
e) Compuneți clasa TestPolitie în care instanţiați clasele programate și testați metodele acestora. 

4. Modelați un sistem de calcul al salariilor pentru diferite tipuri de angajați.

a) Creați clasa abstractă Angajat, care va conține:
- atributul nume (String);
- atributul salariuBaza (double);
- constructor pentru inițializare;
- metodă concretă afisareNume();
- metode abstracte: calculeazaSalariu() și calculeazaBonus()
b) Creați cel puțin 3 clase:
- Programator. Despre programator se știe că bonus = 20% din salariul de bază și salariu final = salariuBaza + bonus.
- Manager. Despre manager se știe că bonus = 35% din salariul de bază și salariu final = salariuBaza + bonus
- Intern, despre inter se știe că bonus = 0 și salariu final = salariuBaza
c) În metoda main:
- creați un array de tip Angajat;
- adăugați obiecte (ex: 5000, 8000, 3000);
- pentru fiecare:
- afișați numele
- calculați și afișați bonusul
- calculați și afișați salariul final
- calculați salariul total al tuturor angajaților
- afișați angajatul cu salariul cel mai mare


5. Se dorește modelarea unui sistem de calcul al costului total pentru diferite tipuri de comenzi online.
a. Creați clasa abstractă Comanda, care va conține:
- atributul client (String);
- atributul valoareProduse (double);
- constructor pentru inițializare;
- metodă concretă afisareClient();
- metode abstracte: calculeazaLivrare() și calculeazaTotal()
b. Creați cel puțin 3 clase:
- ComandaStandard, despre care se cunoaște că costul de livrare este 50 lei, iar totalul se va calcula conform formulei: total = valoareProduse + livrare
- ComandaExpress, despre care se cunoaște că costul de livrare este 100 lei, iar totalul se va calcula conform formulei: total = valoareProduse + livrare
- ComandaPremium, despre care se cunoaște că costul de livrare este 0 lei, iar totalul se va calcula conform formulei: total = valoareProduse (livrare gratuită)
c. În metoda main:
- creați un array de tip Comanda;
- adăugați obiecte (ex: 500 lei, 300 lei etc.);
- pentru fiecare:
- afișați clientul
- calculați livrarea
- calculați totalul
- aplicați reducere de 10% pentru comenzile peste 500 lei
- afișați comanda cu cel mai mare total

Succes! 
❤️

marți, 31 martie 2026

Set. HashSet. LinkedHashSet. TreeSet

După ce am studiat colecțiile de tip List, unde elementele sunt ordonate și pot apărea duplicate, este important să analizăm și o altă categorie esențială din cadrul colecțiilor Java — Set.

Spre deosebire de liste, structurile de tip
Set au o regulă foarte clară: nu permit elemente duplicate. Încercarea de a adăuga un element deja prezent în Set nu va avea efect. Această caracteristică le face extrem de utile în situațiile în care dorim să lucrăm cu date unice, cum ar fi eliminarea valorilor repetate sau verificarea rapidă a existenței unui element.

Un alt aspect important este că, în funcție de implementare, seturile pot:
  • să nu păstreze ordinea elementelor - clasa HashSet
  • să păstreze ordinea de inserare - clasa LinkedHashSet
  • sau să sorteze automat elementele - clasa TreeSet
În continuare, vom examina fiecare clasă separat, evidențiind modul de funcționare și situațiile în care este recomandată utilizarea acesteia.

Interfața Set pune la dispoziție un set de metode care permit gestionarea eficientă a colecțiilor fără elemente duplicate. Aceste metode oferă posibilitatea de a adăuga, elimina, verifica și parcurge elementele, indiferent de tipul concret de implementare utilizat. Cunoașterea acestor metode este extrem de importantă deoarece ele reprezintă baza lucrului cu toate tipurile de seturi (HashSet, LinkedHashSet, TreeSet). 
Astfel, odată înțelese, ele pot fi aplicate ușor în orice context, fără a fi necesară învățarea separată pentru fiecare clasă. Deoarece noi cunoaștem cu toate clasele care implementează o interfață conțin implementare pentru metodele interfeței.
Deci, interfața Set are următoarele metode principale:
  • boolean add(E element) - adaugă un element în set. Returnează true dacă setul nu conține deja elementul adăugat.
  • boolean contains(Object o)) - verifică dacă setul conține un anumit element.
  • boolean remove(Object o) - elimină un element din set. Returnează true dacă setul conținea elementul șters.
  • int size() - returnează numărul de elemente din set.
  • boolean isEmpty() - verifică dacă setul este gol (nu conține elemente).
  • void clear() - elimină toate elementele din set.
  • Iterator<E> iterator() - returnează un iterator peste elementele din set.
  • Object[] toArray() - returnează un tablou care conține toate elementele din set.
  • <T> T[] toArray(T[] a) - returnează un tablou care conține toate elementele din set, într-un tablou specificat.
  • boolean containsAll(Collection<?> c) - verifică dacă setul conține toate elementele dintr-o altă colecție.
  • boolean addAll(Collection<? extends E> c) - adaugă toate elementele dintr-o altă colecție în set.
  • boolean removeAll(Collection<?> c) - elimină toate elementele din set care sunt prezente și într-o altă colecție.
  • boolean equals(Object o) - verifică dacă setul este egal cu un alt obiect.
  • int hashCode() - returnează codul hash pentru set.
  • boolean removeIf(Predicate<? super E> filter) - elimină elementele care respectă o condiție. Vedeți expresiile Lambda aici https://musteatadidactic.blogspot.com/2026/02/expresiile-lambda.html
  • void forEach(Consumer<? super E> action)- parcurge fiecare element și aplică o acțiune. Acceptă ca parametru o expresie lambda.
Interfața Set nu poate fi utilizată direct, deoarece este doar un model. Pentru a lucra efectiv cu date, avem nevoie de o clasă concretă care să implementeze această interfață.
Una dintre cele mai frecvent utilizate implementări ale interfeței
Set este HashSet. Aceasta permite stocarea elementelor într-un mod rapid și eficient, utilizând mecanismul de hashing, și asigură în același timp unicitatea acestora.
În continuare, vom analiza clasa
HashSet, modul de funcționare și principalele operații disponibile.
Clasa
HashSet reprezintă o colecție în care elementele sunt organizate prin hashing, ceea ce permite un acces foarte rapid. Operațiile de adăugare, eliminare și căutare au, în medie, o complexitate de timp O(1), ceea ce le face potrivite pentru lucrul cu volume mari de date. Această clasă nu permite elemente duplicate și, în mod obișnuit, nu acceptă valori nule.
Constructori importanți:
  • HashSet() – creează un set gol, utilizând valorile implicite
  • HashSet(Collection<? extends E> c) – creează un set care conține elementele unei colecții existente
Exemplul 1 Creează o listă de tip HashSet ce va conține discipline, adaugă câteva elemente (fără duplicate), și le afișează folosind trei metode diferite de parcurgere, afișează și numărul total de elemente in listă.
import java.util.HashSet;
import java.util.Set;

public class Main{
public static void main(String[] args) {
Set<String> discipline = new HashSet<>();
discipline.add("Matematica");
discipline.add("Informatica");
discipline.add("Fizica");
discipline.add("Matematica");
System.out.println("\u001B[4m\033[1mAfișare directă\033[0m\u001B[0m");
System.out.println(discipline);
System.out.println("\u001B[4m\033[1m\nParcurgere cu for îmbunătățit\033[0m\u001B[0m");
for (String d : discipline) {
System.out.println(d);
}
System.out.println("\u001B[4m\033[1m\nParcurgere cu expresie lambda\033[0m\u001B[0m");
discipline.forEach(x -> System.out.println(x));
System.out.println("\u001B[4m\033[1m\nNumar elemente:\033[0m\u001B[0m " + discipline.size());
}}
Atenție la elementele care au fost adăugate în listă și la cele care au fost afișate! 👀 Ce observați ? Evident, elementele duplicat nu sunt adăugate în listă 👌 
Detalii despre clasa HashSet direct din sursa oficială https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html

Exemplul 2 Vom modifica exemplul de mai sus prin crearea unei liste de tip  ArrayList care permite elemente duplicat. Observați diferențele prin compararea rezultatelor.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> discipline = new ArrayList<>();
discipline.add("Matematica");
discipline.add("Informatica");
discipline.add("Fizica");
discipline.add("Matematica");
System.out.println("\u001B[4m\033[1m\nParcurgere cu expresie lambda\033[0m\u001B[0m");
discipline.forEach(x -> System.out.println(x));
System.out.println("\u001B[4m\033[1m\nNumar elemente:\033[0m\u001B[0m " + discipline.size());
}}
Clasa LinkedHashSet implementează interfeța Set care combină unicitatea elementelor cu menținerea ordinii de inserare. Practic, ea păstrează elementele exact în ordinea în care au fost adăugate, spre deosebire de HashSet, care nu garantează nicio ordine.
Această clasă folosește un hashing pentru a asigura unicitatea elementelor, adică nu permite duplicate și  folosește o listă dublu înlănțuită internă pentru a păstra ordinea de inserare. Oferă operații rapide de adăugare, eliminare și căutare, aproape de O(1), însă are un consum mai mare de memorie comparativ cu HashSet, din cauza listei dublu înlănțuite, adică este puțin mai lent decât HashSet la operații simple.
Constructori importanți: 
  • LinkedHashSet() - creează un set gol fără parametri. Menține ordinea de inserare.
  • LinkedHashSet(Collection<? extends E> c) - creează un set care conține toate elementele unei colecții existente. Elimină duplicatele automat.
Exemplul 3 Vom crea o listă de tip LinkedHashSet în care vom stoca elemente de tip Elev
import java.util.LinkedHashSet;
import java.util.Set;
class Elev {
private String nume;
private int nota;
public Elev(String nume, int nota) {
this.nume = nume;
this.nota = nota;
}
@Override
public String toString() {
return nume + " - Nota: " + nota;
}
}
public class Main {
public static void main(String[] args) {
Set<Elev> elevi = new LinkedHashSet<>();
elevi.add(new Elev("Ana", 9));
elevi.add(new Elev("Ion", 7));
elevi.add(new Elev("Maria", 10));
elevi.add(new Elev("Bogdan", 8));
elevi.add(new Elev("Ana", 9));
System.out.println("Lista elevilor:");
elevi.forEach(x -> System.out.println(x));
}
}

După cum observați, necătând la faptul că
LinkedHashSet nu premite elemente duplicat, exemplul nostru are un alt rezultat și avem două persoane cu aceleași valori, este din motiv că operatorul new() crează un nou obiect în sistem și acesta va avea codul hash diferit de obiectul anterior, iar limbajul Java compară implicit doar acest cod, nu și conținutul obiectelor. În acest caz este necesară supradefinirea metodelor equals() și hashCode().
Exemplul 4 Vom crea o listă de tip LinkedHashSet în care vom stoca elemente de tip Elev. Vom supradefini metodele equals() și hashCode() pentru a nu permite două obiecte cu același conținut. 
import java.util.LinkedHashSet;
import java.util.Set;
class Elev {
private String nume;
private int nota;
public Elev(String nume, int nota) {
this.nume = nume;
this.nota = nota;
}
@Override
public String toString() {
return nume + " - Nota: " + nota;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Elev)) return false;
Elev elev = (Elev) o;
return nota == elev.nota && nume.equals(elev.nume);
}
@Override
public int hashCode() {
return nume.hashCode() + nota;
}
}
public class Main {
public static void main(String[] args) {
Set<Elev> elevi = new LinkedHashSet<>();
elevi.add(new Elev("Ana", 9));
elevi.add(new Elev("Ion", 7));
elevi.add(new Elev("Maria", 10));
elevi.add(new Elev("Bogdan", 8));
elevi.add(new Elev("Ana", 9));
System.out.println("Lista elevilor:");
elevi.forEach(x -> System.out.println(x));
}}
În proiecte reale pentru a asigura unicitatea fiecărui elev în colecție, vom lua în considerare un element care îl identifică în mod unic, cum ar fi un ID sau un cod personal (IDNP), astfel încât să nu putem avea doi elevi cu același identificator, chiar dacă au aceeași notă sau același nume.
Clasa TreeSet este o implementare a interfeței NavigableSet, care stochează elementele sortate automat, deci și aici elemente duplicate nu sunt permise și nici
valorile null. Are la bază arbore binar de căutare. Operațiile de adăugare, ștergere și căutare au complexitate O(log n)
Constructori importanți: 
  • TreeSet() – creează un set gol cu ordonare naturală. 
  • TreeSet(Collection<? extends E> c) – creează un set cu elementele dintr-o colecție existentă și le sortează.
  • TreeSet(Comparator<? super E> comparator) – creează un set gol care folosește un comparator personalizat pentru sortare.
Exemplul 5 Vom crea o listă de tip TreeSet care va conține elemente întregi.
import java.util.*;
public class Main {
public static void main(String[] args) {
Set<Integer> numere = new TreeSet<>();
numere.add(5);
numere.add(2);
numere.add(8);
numere.add(3);
numere.add(5);
numere.add(1);
System.out.println("Numere sortate automat:");
for (Integer n : numere) {
System.out.print(n+" ");
}}}

După cum observați elementele au fost automat sortate în ordine crescătoare, iar duplicatele au fost omise. 
Exemplul  6 Vom crea o listă de tip TreeSet care va conține elemente întregi, dar vor fi sortate automat în ordine descrescătoare.
import java.util.*;
public class Main {
public static void main(String[] args) {
Set<Integer> numere = new TreeSet<>(Comparator.reverseOrder());
numere.add(5);
numere.add(2);
numere.add(8);
numere.add(3);
numere.add(5);
numere.add(1);
System.out.println("Numere sortate descrescător:");
for (Integer n : numere) {
System.out.print(n+" ");
}}}

Exemplul  7 Vom crea o listă de tip TreeSet care va conține elemente de tip Elev sortate descrescător după notă. Fără elemente duplicat.
import java.util.*;
class Elev {
private String nume;
private int nota;
public Elev(String nume, int nota) {
this.nume = nume;
this.nota = nota;
}
public String getNume() {
return nume;
}
public int getNota() {
return nota;
}
@Override
public String toString() {
return nume + " - Nota: " + nota;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Elev)) return false;
Elev elev = (Elev) o;
return nota == elev.nota && nume.equals(elev.nume);
}
@Override
public int hashCode() {
return nume.hashCode() + nota;
}}

public class Main {
public static void main(String[] args) {
Set<Elev> elevi = new TreeSet<>(Comparator.comparingInt(Elev::getNota).reversed());
elevi.add(new Elev("Ana", 9));
elevi.add(new Elev("Ion", 7));
elevi.add(new Elev("Maria", 10));
elevi.add(new Elev("Bogdan", 8));
elevi.add(new Elev("Ana", 9));
System.out.println("Elevi sortati descrescător după nota:");
elevi.forEach(x -> System.out.println(x));
}
}
Pentru a efectua o sortare alfabetică după nume este suficient să folosim constructorul cu următorul parametru personalizat de sortare: 
Set<Elev> elevi = new TreeSet<>(Comparator.comparing(Elev::getNume));
Pentru o sortare pe două nivele putem folosi constructor de forma celui ce urmează care va efectua o sortare alfabetică după nume și descrescătoare după notă:  
        Comparator<Elev> comparator = Comparator.comparing(Elev::getNume.thenComparing (Comparator.comparingInt(Elev::getNota).reversed());
Pentru o sortare pe trei nivele amputea utiliza constructorul personalizat:
Comparator<Elev> comparator = Comparator.comparing(Elev::getNume.thenComparing(Elev::getPrenume.thenComparing (Comparator.comparingInt(Elev::getNota).reversed());

Pentru a evidenția diferențele și avantajele fiecărei implementări a interfeței Set, voi atașa cestei teme tabelul comparativ între HashSet, LinkedHashSet și TreeSet, care este concentrat pe ordonare, performanță și modul de gestionare a elementelor duplicat
Caracteristică HashSet LinkedHashSet TreeSet
Interfață implementată Set Set NavigableSet (extinde SortedSet și Set)
Ordinea elementelor Nu este garantată Păstrează ordinea de inserare Elementele sunt sortate natural (alfabetic/numeric) sau după Comparator
Permite duplicate Nu Nu Nu
Permite elemente null Da (doar un singur null) Da (doar un singur null) Nu (aruncă NullPointerException)
Complexitate adăugare/ștergere/căutare O(1) în medie O(1) în medie O(log n)
Structură internă Tabel hash Tabel hash + listă dublu înlănțuită Arbore binar de căutare
Avantaje Foarte rapid Rapid + ordinea elementelor păstrată Elemente sortate, navigare facilă
Dezavantaje Ordinea nu este păstrată Consum mai mare de memorie decât HashSet Operații mai lente decât HashSet/LinkedHashSet
Când se folosește Când ordinea nu contează și avem nevoie de viteză Când vrem ordinea de inserare și unicitate Când avem nevoie de elemente sortate automat

În concluzie, alegerea corectă a unei implementări a interfeței
Set depinde de cerințele aplicației: dacă este nevoie de viteză, se va utiliza HashSet, dacă se dorește păstrarea ordinii de inserare se va utiliza LinkedHashSet, iar dacă este necesară sortarea automată a elementelor – TreeSet. Toate aceste colecții asigură unicitatea elementelor, însă diferă prin modul de organizare internă și performanță.
Vă încurajez să testați fiecare tip de set prin exemple proprii și să observați diferențele în comportament – aceasta este cea mai bună metodă de învățare în programare, testați, modificați, ajustați, corectați erori de compilare și execuție.

Vă doresc o zi deosebit de frumoasă!
❤️

luni, 30 martie 2026

Clase și metode abstracte

Clasele abstracte în Java sunt un concept fundamental în Programarea orientată spre obiecte.

Deseori, atunci când lucrăm cu clasele derivate apare problema că pentru superclasă nu putem preciza implementarea unei metode pentru că subclasele sale au nevoie de implementare specifică fiecăreia. În acest caz pot fi utilizate clasele abstracte.

Java are clase abstracte predefinite. Una fiind clasa abstractă
Number, ce se conține în pachetul java.lang. Această clasă abstractă descrie un număr la general, dar într-o aplicație avem nevoie de număr de un anumit tip (întreg, real, ș.a). Fiecare tip de număr are caracteristicele sale însă toate exprimă valori numerice, fiecare în felul său. Clasa abstractă Number servește ca superclasă pentru clasele concrete Byte, Double, Float, Integer, Short şi Long, denumite și clase Wrapper sau clase înfășurătoare, despre care am menționat pe parcursul lecțiilor anterioare.

Obiecte de tip
Number nu putem instanția, însă putem instanția obiecte de tip Integer, Double, Float, etc.

O clasă declarată folosind cuvântul rezervat abstract este numită clasă abstractă. Așa tip de clasă nu poate fi instanţiată direct. Cu alte cuvinte, nu se pot crea obiecte direct pentru clasa abstractă. Scopul principal al claselor abstracte este de a defini caracteristici și comportamente comune pentru un grup de clase derivate.

Clasele abstracte pot defini metode și variabile pe care subclasele trebuie să le implementeze sau să le redefinească. Astfel, clasele abstracte pot oferi o implementare parțială a unei funcționalități (metode), lăsând detaliile specifice să fie implementate de către subclase.

Pentru a defini o clasă abstractă în Java, folosim cuvântul cheie abstract înaintea definiției clasei:
[public] abstract class numeClasaAbstracta
[ extends Superclasa ]
{
// declarații de atribute si metode
}

O clasă abstractă poate conține atât metode abstracte (metode care sunt declarate, dar nu sunt implementate în clasă), cât și metode concrete (metode care au o implementare).

Rețineți !
1. Clasa abstractă nu conține modificatorul
final;
2. Clasa abstractă conține metode abstracte, nu au implementare în clasa dată;
3. Clasa abstractă poate să nu aibă nici o metodă abstractă;
4. Orice clasă ce are măcar o metodă abstractă trebuie să fie şi ea abstractă;
5. O clasă nu poate fi concomitent finală şi abstractă;
6. Subclasa unei clase abstracte trebuie să conțină cod pentru toate metodele abstracte declarate în superclasa abstractă, în caz contrar subclasa trebuie să fie şi ea abstractă;
7. Clasa abstractă impune subclasele sale să implementeze metode comune şi le permite să implementeze şi metode proprii;
8. Constructorii și câmpurile clasei nu pot fi abstract.

O metodă abstractă este o metodă fără implementare și poate fi doar în corpul unei clase abstracte, conține obligatoriu cuvântul rezervat abstract în semnătura acesteia:
abstract tipMetoda numeMetoda ([lista_parametri_formali]);

Rețineți !
1. Metodele abstracte conțin semnul ,,;’’ ce înlocuiește corpul metodei;
2. O metodă declarată public poate fi abstractă;
3. O metodă statică nu poate fi abstractă, pentru că nu poate fi rescrisă;
4. Metodele abstracte nu pot fi private pentru că scopul acestora este de a fi implementate într-o clasă copil.

Exemplu 1 Creați un program Java format din:
1. clasa abstractă Figura care va conține 2 metode publice abstracte fără parametri: double Arie() şi double Perimetru().
2. clasa Cerc ce extinde clasa abstractă Figura și va conține variabila privată raza, constructorul clasei cu un parametru, metodele Arie() și Perimetru() implementate.
3. clasa Triunghi ce extinde clasa Figura și conține variabila privată latura, constructorul clasei cu un parametru, metodele din Figura implementate.
4. clasa TestFigura.

abstract class Figura{
public abstract double Arie();
public abstract double Perimetru();
}

class Cerc extends Figura{
private double raza;
public Cerc(int raza){ this.raza = raza;}
public double Arie(){
return Math.PI*raza*raza;
}
public double Perimetru(){
return 2*Math.PI*raza;
}}

class Triunghi extends Figura{
private double latura;
public Triunghi(double latura){this.latura = latura;}
public double Arie(){
return Math.sqrt(3)/4*latura*latura;
}
public double Perimetru(){
return 3*latura;
}}

public class TestFigura {
public static void main(String[] args) {
System.out.println("-------------------------------------");
Cerc obCerc = new Cerc(3);
System.out.println("Aria cercului = "+obCerc.Arie());
System.out.println("Perimetru cercului"+obCerc.Perimetru());
System.out.println("-------------------------------------");
Triunghi obTriunghi = new Triunghi(5);
System.out.println("Aria triunghi = "+obTriunghi.Arie());
System.out.println("Perim. Triunghi "+obTriunghi.Perimetru());
}}


Avantajele utilizării claselor abstracte:
1. Clasele abstracte ajută la organizarea și structurarea codului prin definirea unor șabloane comune pentru obiecte similare. Acestea permit separarea logicii comune și a detaliilor specifice în clase separate, ușurând înțelegerea și gestionarea codului.
2. Prin intermediul claselor abstracte, putem defini comportamente și caracteristici comune, care pot fi apoi extinse și adaptate în clasele derivate. Acest lucru promovează reutilizarea codului și permite crearea de noi funcționalități pe baza celor existente.

Dezavantajele utilizării claselor abstracte:
1. Utilizarea excesivă a claselor abstracte poate duce la creșterea complexității în proiecte mari și complexe. Definirea unei ierarhii de clase prea profunde sau prea interconectate poate face codul mai greu de înțeles și de întreținut.
2. Clasele abstracte pot crea dependențe strânse între clasele din ierarhia de moștenire. Aceasta poate duce la dificultăți în refactorizare, deoarece modificările aduse unei clase abstracte pot avea un impact asupra claselor care o extind.

Vă propun să urmăriți un tutorial practic în care se evidențiază utilizarea claselor abstracte:


Detalii complexe despre clasele abstracte consultați aici: 👉https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

Să aveți o zi deosebită! 
❤️