This is an old revision of the document!


Breviar 6

Clase abstracte și metode abstracte

Introducere

În proiectarea unei aplicații este adesea necesar să reprezentăm, cu ajutorul claselor, concepte abstracte, care nu pot fi instanțiate și care servesc doar la dezvoltarea ulterioară a unor clase ce descriu obiecte concrete.

De exemplu, în pachetul java.lang există clasa abstractă Number, care modelează conceptul generic de „număr”. Într-un program nu avem însă nevoie de „numere generice”, ci de numere cu un anumit tip: întregi, reale etc. Clasa Number servește ca superclasă pentru clasele concrete Byte, Double, Float, Integer, Long și Short, care implementează obiecte pentru descrierea numerelor de un anumit tip.

O clasă abstractă nu poate fi instanțiată. În locul ei vom utiliza subclasele sale care nu sunt abstracte.

Declararea claselor abstracte

O clasă se declară ca fiind abstractă folosind cuvântul-cheie abstract. O clasă abstractă poate avea modificatorul public, accesul implicit fiind la nivel de pachet. Ea nu poate specifica modificatorul final, deoarece combinația `abstract final` este semnalată ca eroare de compilare (o clasă `final` nu poate fi extinsă, iar o clasă `abstract` trebuie extinsă).

O clasă abstractă poate conține aceleași elemente membre ca o clasă obișnuită, dar și metode abstracte – adică metode fără implementare efectivă.

public abstract class Patrulater {
    class Point {
        int x, y;
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
 
    Point p1, p2, p3, p4;
 
    // Metode abstracte
    abstract int calculPerimetru();
    abstract double calculArie();
}
Metode abstracte

Spre deosebire de clasele obișnuite, care trebuie să furnizeze implementări pentru toate metodele declarate, o clasă abstractă poate conține metode fără implementare. Astfel de metode se numesc metode abstracte și pot apărea doar în clase abstracte.

În declararea unei metode abstracte se folosește cuvântul-cheie abstract.

Exemplu practic

Paralelogramul, dreptunghiul, pătratul și rombul sunt figuri geometrice ce pot fi caracterizate prin patru puncte din plan. Pentru fiecare astfel de figură există o formulă prin care îi putem determina aria, știind coordonatele celor patru puncte sau alte date suplimentare.

Prin urmare, clasele care modelează aceste figuri pot fi derivate dintr-o clasă abstractă Patrulater. Deoarece pentru fiecare figură avem o formulă diferită de calcul al ariei, este normal ca Patrulater să conțină o metodă calculArie().

Se pune însă problema implementării acestei metode în clasa de bază, deoarece fiecare patrulater concret are un mod propriu de calcul. Într-o astfel de situație, varianta corectă este ca metoda calculArie() să fie declarată abstractă, fără implementare. Implicit, clasa Patrulater devine una abstractă, deoarece conține o metodă abstractă.

Observații

O clasă poate fi abstractă chiar dacă nu conține nicio metodă abstractă.

Dacă o clasă conține cel puțin o metodă abstractă, atunci clasa trebuie declarată abstractă; în caz contrar, se semnalează o eroare la compilare.

O subclasă a unei clase abstracte trebuie să implementeze toate metodele abstracte ale superclasei sale. Dacă nu o face, subclasa trebuie, la rândul ei, declarată abstractă. Nu pot fi instanțiate clase care conțin metode neimplementate!

Interfețe

Introducere

Interfețele duc conceptul de clasă abstractă cu un pas înainte, prin eliminarea oricăror implementări de metode, punând în practică unul dintre conceptele programării orientate pe obiecte: separarea modelului unui obiect (interfața) de implementarea sa. O interfață poate fi privită ca un protocol de comunicare între obiecte.

Definiție și comportament impus

O interfață Java definește un set de metode, dar nu specifică nicio implementare pentru ele. O clasă care implementează o interfață trebuie, obligatoriu, să specifice implementări pentru toate metodele interfeței, supunându-se, așadar, unui anumit comportament.

O interfață este o colecție de metode fără implementare și declarații de constante.

Acces și modificatori

O interfață poate avea un singur modificator de acces, iar acesta este public. O interfață publică este accesibilă tuturor claselor, indiferent de pachetul din care fac parte; în lipsa lui, nivelul implicit de acces este la nivelul pachetului în care se află interfața.

Extinderea interfețelor

O interfață poate extinde oricâte interfețe; acestea se numesc superinterfețe.

Cod sursă Java
interface Inf1 extends Comparable {
    public void method1();
}
 
interface Inf2 extends Inf1 {
    public void method2();
}
 
public class Test implements Inf2 {
    public void method2() {
        // Metoda din interfața Inf2
    }
 
    public void method1() {
        // Metoda din interfața Inf1
    }
 
    public int compareTo(Object o) {
        // Metoda din interfața Comparable
        return 0;
    }
}

Compararea elementelor

Introducere

Să presupunem că avem o listă, de tip ArrayList, cu elemente de tip Student și dorim să sortăm elementele din această listă după media anilor, presupunând că Student este o clasă ce conține printre membrii săi o variabilă ce reține media anilor.

Pentru realizarea acestui lucru există două posibilități, ce vor fi detaliate în continuare, folosind Comparable și Comparator.

Interfața Comparable

Pentru a putea compara direct o instanță a unui tip (clasă definită de utilizator) cu o altă instanță, este necesar ca tipul respectiv să implementeze interfața Comparable. Această interfață conține o singură metodă, care returnează:

- un număr pozitiv – dacă instanța curentă este mai mare decât cea primită ca parametru; - 0 – dacă instanțele sunt egale; - un număr negativ – dacă instanța curentă este mai mică decât cea primită ca parametru.

class Student implements Comparable {
    private String nume;
    private double medie;
 
    public Student(String nume, double medie) {
        this.nume = nume;
        this.medie = medie;
    }
 
    @Override
    public int compareTo(Object o) {
        Student obj = (Student) o;
        return (int)(this.medie - obj.medie);
    }
 
    public String toString() {
        String result = nume + " " + medie;
        return result;
    }
 
    public static void main(String args[]) {
        Vector v = new Vector();
        v.add(new Student("Popescu", 10));
        v.add(new Student("Ionescu", 9.75));
        v.add(new Student("Popa", 9.80));
        Collections.sort(v);
        System.out.println(v);
    }
}
Interfața Comparator

Interfața Comparator oferă o altă modalitate de comparare, separând logica de comparație de clasa comparată. Aceasta definește metoda compare(Object o1, Object o2), care returnează un număr pozitiv, zero sau negativ în funcție de ordinea dorită între cele două obiecte.

class StudentComparator implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        Student s1 = (Student) o1;
        Student s2 = (Student) o2;
 
        if(s1.getMedie() > s2.getMedie()) {
            return 1;
        } else if(s1.getMedie() == s2.getMedie()) {
            return 0;
        } else {
            return -1;
        }
    }
}
 
class Student {
    private String nume;
    private double medie;
 
    public Student(String nume, double medie) {
        this.nume = nume;
        this.medie = medie;
    }
 
    public String toString() {
        String result = nume + " " + medie;
        return result;
    }
 
    public double getMedie() {
        return this.medie;
    }
 
    public static void main(String args[]) {
        Vector v = new Vector();
        v.add(new Student("Popescu", 10));
        v.add(new Student("Ionescu", 9.75));
        v.add(new Student("Popa", 9.80));
        Collections.sort(v, new StudentComparator());
        System.out.println(v);
    }
}
poo/breviare/breviar-06.1762596297.txt.gz · Last modified: 2025/11/08 12:04 by george.tudor1906
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