ALGO25 / BLOG

Java: clase, interfețe și încapsulare

Înțelege clasele, obiectele, interfețele și încapsularea în Java. Construiește o sarcină cu un colaborator primit prin constructor și verifică starea.

Un obiect reunește o stare și operațiile permise asupra ei. Vom modela o sarcină care are un titlu și poate fi finalizată. Separăm regula de pregătire a titlului într-o interfață, pentru a înțelege mai târziu injecția de dependențe din Spring.

Ce trebuie să știi deja

Ai nevoie de variabile, metode și controlul execuției. Exemplul folosește Java 21. Clasele sunt incluse în Main ca să poți compila un singur fișier; într-un proiect mai mare le-am putea separa în fișiere și pachete cu responsabilități clare.

Contractul didactic presupune un titlu nenul și o politică nenulă. Nu pretindem încă validarea tuturor intrărilor. Acea responsabilitate va fi introdusă explicit, întâi prin excepții și apoi la granița unui API HTTP.

Obiectul și colaboratorul său

public class Main {
    interface TitlePolicy {
        String normalize(String title);
    }

    static final class TrimmedTitle implements TitlePolicy {
        public String normalize(String title) {
            return title.strip();
        }
    }

    static final class Task {
        private final String title;
        private boolean completed;

        Task(String title, TitlePolicy policy) {
            this.title = policy.normalize(title);
        }

        void complete() {
            completed = true;
        }

        String summary() {
            return title + ": " + completed;
        }
    }

    public static void main(String[] args) {
        Task task = new Task("  Invata Java  ", new TrimmedTitle());
        System.out.println(task.summary());
        task.complete();
        System.out.println(task.summary());
    }
}

După javac Main.java și java Main, rezultatul este Invata Java: false, apoi Invata Java: true, pe linii separate. Spațiile de la capetele titlului au fost eliminate înainte de memorare. Între cele două afișări se schimbă numai starea de finalizare.

Încapsularea păstrează regulile într-un loc

Câmpurile sunt private, deci codul din afara clasei nu le folosește drept interfață publică. Operația complete() exprimă o intenție. Dacă am expune orice câmp pentru scriere, fiecare apelant ar trebui să cunoască și să respecte aceleași reguli.

final pe câmpul title împiedică reatribuirea lui după inițializare. Nu înseamnă că orice obiect referit de un câmp final este profund imuabil. Aici avem un String imuabil, dar o listă modificabilă ar putea fi schimbată chiar dacă referința către ea este finală.

Constructorul primește datele necesare pentru creare. this.title identifică explicit câmpul obiectului. Metoda summary() produce un text din starea curentă; două apeluri pot da rezultate diferite dacă între ele apelăm complete().

Interfață și implementare

TitlePolicy declară ce operație așteaptă clasa Task. TrimmedTitle oferă o implementare concretă. Obiectul Task primește colaboratorul în constructor și îl folosește fără să construiască el însuși implementarea. Aceasta este injecție de dependențe făcută manual, prin cod Java obișnuit.

Putem furniza o altă implementare care transformă textul după o regulă diferită. Nu trebuie să schimbăm clasa Task pentru fiecare politică. Totuși, nu orice clasă are nevoie de o interfață: introdu-o când exprimă un contract util sau când variația este reală, nu ca ritual.

Compoziție înainte de moștenire inutilă

O sarcină folosește o politică de titlu; nu este o politică de titlu. Relația este de colaborare. Moștenirea ar trebui să exprime o relație de substituire coerentă, nu doar dorința de a reutiliza câteva linii de cod.

La un interviu, poți porni de la cerință: ce se schimbă, ce rămâne stabil și cine deține starea? Răspunsul conduce spre design. O diagramă cu multe interfețe fără o cerință de variație poate ascunde o soluție mai simplă.

Exersează

  1. Apelează complete() de două ori. Rezultatul rămâne finalizat; operația este idempotentă pentru starea acestui obiect.
  2. Adaugă o politică ce păstrează exact titlul. Rezultatul trebuie să conțină și spațiile inițiale. Nu modifica logica din Task.
  3. Creează două sarcini și finalizează numai prima. Verifică faptul că a doua rămâne nefinalizată, fiindcă fiecare instanță are propria stare.

Verifică înainte să continui

Poți continua dacă distingi clasa de instanță, contractul de implementare și câmpul de variabila locală. Explică în două minute cine construiește colaboratorul și cine îl folosește. Urmează excepții, generice și liste, apoi verificarea despre egalitate și colecții.

Întrebări frecvente

O clasă finală nu mai poate avea stare modificabilă?

Poate avea. final pe clasă împiedică extinderea ei prin moștenire, nu modificarea propriilor câmpuri mutabile.

Interfața construiește obiectele?

Nu. Ea definește contractul. În exemplu, new TrimmedTitle() creează instanța implementării.

Injecția de dependențe cere Spring?

Nu. Exemplul o face manual prin constructor. Spring poate gestiona crearea și conectarea obiectelor pentru noi.

De ce nu avem setTitle?

Contractul exemplului fixează titlul la creare. Adăugăm o operație de modificare doar dacă există o cerință și reguli clare.

private înseamnă protecție de securitate a datelor?

Nu este autorizare între utilizatori sau criptare. Este un mecanism al limbajului pentru controlul accesului în cod.

Surse

Clase și obiecte și interfețe Java, consultate la 13 octombrie 2026.