1. Testați în editorul de cod Java codul de la Exemplul 1. Efectuați următoarele modificări:
Creați o nouă listă de tip HashSet ce va conține elemente de tip întreg.
Citiți 10 elemente de la tastatură.
Afișați elementele citite la ecran însoțite de suma acestora.
2. Testați în editorul de cod Java codul de la Exemplul 4. Efectuați următoarele modificări:
Adăugați clasei Elev caracteristica IDNP care reprezintă codul personal al elevului. Modificați întreg codul (constructor, toString(), main()) astfel încât acesta să ruleze cu succes.
Modificați metodele equals() și hashCode() astfel încât acestea să nu admită elevi cu același IDNP în listă.
Citiți datele elevilor dintr-un fișier text.
3. Testați în editorul de cod Java codul de la Exemplul 5. Efectuați următoarele modificări:
Citiți datele dintr-un fișier în care se cunoaște că sunt 20 valori întregi unele dintre care se repetă.
Sortați elementele descrescător.
4. Testați în editorul de cod Java codul de la Exemplul 7. Efectuați următoarele modificări:
Adăugați clasei Elev câmpul grupa, care reprezintă grupa în care elevul studiază. Modificați întreg codul (constructor, toString(), main()) astfel încât acesta să ruleze cu succes.
Sortați elementele crescător după grupă și descrescător după notă.
5. Elaborați un program Java care va conține o listă de tip HashSet cu 10 valori. Afișați lista la ecran. Eliminați folosind instrucțiunea removeIf() toate numerele mai mari de 20.
6. Elaborați un program Java care va înscrie într-o listă elevii în ordinea în care au ridicat mâna să răspundă. Deci va trebuie să păstrezi ordinea participării la discuție și nu se dorește ca fiecare elev să fie înregistrat de două ori. Ce tip de date vei declara lista? Consultă tabelul din repere teoretice! Lista va avea tipul LinkedHashSet și va stoca elemente de tip Elev.
7. Se dorește o aplicație care va crea un clasament al elevilor participanți la competiție. Elaborați un program Java care va înscrie într-o listă elevii și punctajul acestora. Nu se permite elemente duplicat, iar elevii trebuie afișați automat în ordine descrescătoare punctajelor acumulate. Ce tip de date vei declara lista? Consultă tabelul din repere teoretice! Lista va avea tipul TreeSet, pentru că sortează automat elementele, și va stoca elemente de tip Elev.
Implementați următoarele clase și interfețe din diagrama UML într-un proiect java.
Aplicația 2.
O platformă de streaming video are nevoie de o aplicație Java care să calculeze costul abonamentelor și taxele de acces. Aplicația va conține:
a. Clasa Abonament. Este o clasă părinte ce are atributele numeUtilizator (String)și pretBaza (double. Ca funcționalitate are metoda calculeazaPretFinal() care returnează prețul de bază + 15% taxă de serviciu.
b.Interfața AccesOnline. Definește un contract comun pentru accesul la platformă și conține metoda calculeazaTaxaAcces(int oreVizionare);
c.Clasa AbonamentPremium ce moștenește Abonament și implementează interfața AccesOnline. Are ca atribute propriu numarDispozitive (int) și ca funcționalitate supradefinește metoda calculeazaPretFinal() după formula prețul de bază + 15% taxă + 10% extra pentru premium și implementează metoda calculeazaTaxaAcces(int oreVizionare) care va calcula taxa după formula: oreVizionare × 2 + numarDispozitive × 3
d.Clasa FurnizorInternet implementează interfața AccesOnline. Are ca atribute numeFurnizor (String) și tarifPeOra (double), iar ca fucționalitate implementează metoda calculeazaTaxaAcces(int oreVizionare) folosind formula: tarifPeOra × oreVizionare
e. Clasa Test (main) în care instanțiați clasa AbonamentPremium. Afișați prețul final folosind metoda supradefinită. Afișați taxa de acces pentru 5 ore de vizionare. Instanțiați clasa FurnizorInternet. Afișați taxa de acces pentru aceeași durată (5 ore)
Aplicație 3.
O platformă de vânzări online are nevoie de o aplicație Java care va calcula prețurile finale și gestiona livrările. Aplicația va conține: a. Clasa Produs despre care se cunoaște că este o clasă părinte ce are atributele: denumire (String), pretBaza (double) și ca funcționalitate metoda: calculeazaPretFinal() care returnează prețul de bază plus un adaos comercial de 10%. b. Interfața Livrari care definește un contract comun pentru expedierea produselor și are ca metodă abstractă calculCostLivrare(double distantaKm). c. Clasa Laptop care moștenește Produs și implementează Livrari. Clasa are ca atribute proprii: greutateKg (double), iar ca funcționalitate supradefinește metoda calculeazaPretFinal() care returnează prețul de bază la care adaugă 10% adaos comercial și 5% taxa de asigurare, după care implementează metoda calculCostLivrare(double distantaKm) care va calcula costul după formula 2 × distanțaKm + (greutateKg × 5). d. Clasa Curier implementează Livrari și are ca atribute: numeCompanie și tarifPerKm, iar ca funcționalitate implementarea metodei calculCostLivrare(double distantaKm) care va cacula costul folosind formula: tarifPerKm × distanța. e. Creați o clasă Test cu metoda main() în care - Instanțiați clasa Laptop. Afișați prețul final al laptopului folosind metoda supradefinită.
- Afișați costul livrării prin propriul sistem de livrare (clasa Laptop) pentru o distanță de 10 km.
- Instanțiați clasa Curier. Afișați costul livrării folosind serviciul extern (clasa Curier) pentru aceeași distanță.
Aplicație 4. O platformă de gestiune a resurselor umane (HR) pentru o companie IT are nevoie de o aplicație Java care va calcula salariile nete și va gestiona alocarea angajaților pe proiecte. Aplicația va conține: a. Clasa Angajat - clasă părinte cu atributele: nume (String), salariuBrutLuna (double) și metoda calculeazaSalariuNet() care returnează salariul brut minus un impozit de 10%.
b. Interfața AlocariProiecte care definește contractul pentru achitările pe proiecte cu metoda abstractă double calculeazaOreBonus(double oreProiect).
c. Clasa Programator care moștenește Angajat și implementează AlocariProiecte. Are atribute proprii: nivelExperienta (int, 1-5) și funcționalități supradefinește calculeazaSalariuNet() returnând salariul brut minus 10% impozit plus 8% bonus de performanță bazat pe nivel și implementează calculeazaOreBonus(double oreProiect) după formula: oreProiect × (nivelExperienta × 2).
d. Clasa ProiectExtern implementează AlocariProiecte cu atribute: numeClient (String) și rataOrara (double), implementând calculeazaOreBonus(double oreProiect) folosind formula: rataOrara × oreProiect.
e. Clasa Test cu metoda main() în care:
- Instanțiați clasa Programator
- Afișați salariul net folosind metoda supradefinită.
- Afișați bonusul pentru 20 ore pe un proiect intern (prin Programator).
- Instanțiați clasa ProiectExtern.
- Afișați bonusul pentru aceleași 20 ore prin proiect extern.
Aplicație 5. O companie de energie electrică are nevoie de o aplicație Java pentru calculul facturilor și taxelor suplimentare în funcție de tipul clientului.
a. Clasa Consumator care Este o clasă părinte care conține atributele: numeClient (String), consumKWh (double) și pretPerKWh (double). Ca funcționalitate conține metoda calculeazaFactura() care returnează costulfacturii alculat după formula: consumKWh × pretPerKWh
b. Interfața Taxare ce definește metoda calculeazaTaxe().
c. Clasa ConsumatorCasnic ce moștenește Consumator și implementează interfața Taxare. Are atributul areReducereSociala (boolean). Ca funcționalitate supradefinește calculeazaFactura(): unde, dacă consumKWh ≤ 100 facturei i se atribuie preț normal, iar dacă consumKWh > 100 atunci aplică +20% tarif; implementează calculeazaTaxe(): care afișează o taxă fixă de 30 lei, sau se scad 20 lei dacă areReducereSociala d. Clasa ConsumatorIndustrial moștenește Consumator și implementează interfața Taxare. Are ca atribute oreVarf (int), iar ca funcționalitate supradefinește calculeazaFactura() calculând conform formulei: cost normal + (oreVarf × 10 lei penalizare) și implementează calculeazaTaxe() 5% din factura totală
e. Clasa FurnizorAlternativ ce implementează interfața Taxare și are ca atribute: abonamentLunar (double), iar ca funcționalitate metoda calculeazaTaxe() ce returnează abonamentLunar + 10% TVA
f. Clasa Test ce conține matoda main() în care:
- Instanțiați ConsumatorCasnic
- Afișați factura
- Afișați taxele
- Instanțiați ConsumatorIndustrial
- Afișați factura
- Afișați taxele
- Instanțiați FurnizorAlternativ
- Afișați taxele
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.
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{
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ă 👌
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");
ClasaLinkedHashSet 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());
Exemplul 7Vom 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ă:
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.
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:
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 1Creaț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;}
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: