Modificatori de acces și încapsulare
Toți membrii unei clase în limbajul Java - câmpurile și metodele - au modificatori de acces. În temele anterioare, ne-am întâlnit deja cu modificatorul public. Modificatorii de acces permit stabilirea domeniului de vizibilitate pentru membrii clasei, adică contextul în care o variabilă sau o metodă poate fi utilizată.
În Java sunt folosiți următorii modificatori de acces:
- public: clasă publică sau membru al unei clase accesibilă tuturor. Câmpurile și metodele declarate cu modificatorul public sunt vizibile altor clase din pachetul curent și din pachetele externe
- private: clasă privată sau membru al unei clase, opusul modificatorului public. O clasă privată sau un membru al unei clase este accesibil doar din codul din aceeași clasă
- protected: acest tip de clasă sau membru al unei clase este accesibil din orice loc din clasa curentă sau din pachet, precum și din clasele derivate, chiar dacă acestea sunt în alte pachete
- Modificator implicit: Lipsa unui modificator la un câmp sau metodă a unei clase implică aplicarea modificatorului implicit. Aceste câmpuri sau metode sunt vizibile tuturor claselor din pachetul curent
Să analizăm modificatorii de acces în exemplul următor:
public class Program{
public static void main(String[] args) {
Person kate = new Person("Kate", 32, "Baker Street", "+12334567");
kate.displayName(); // normal, metodă publică
kate.displayAge(); // normal, metodă cu modificator implicit
kate.displayPhone(); // normal, metodă protected
//kate.displayAddress(); // ! Eroare, metodă private
System.out.println(kate.name); // normal, modificator implicit
System.out.println(kate.address); // normal, modificator public
System.out.println(kate.age); // normal, modificator protected
//System.out.println(kate.phone); // ! Eroare, modificator private
}
}
class Person{
String name;
protected int age;
public String address;
private String phone;
public Person(String name, int age, String address, String phone){
this.name = name;
this.age = age;
this.address = address;
this.phone = phone;
}
public void displayName(){
System.out.printf("Name: %s \n", name);
}
void displayAge(){
System.out.printf("Age: %d \n", age);
}
private void displayAddress(){
System.out.printf("Address: %s \n", address);
}
protected void displayPhone(){
System.out.printf("Phone: %s \n", phone);
}
}
În acest caz, ambele clase sunt localizate în același pachet - pachetul implicit, astfel încât în clasa Program putem folosi toate metodele și variabilele clasei Person, care au modificator implicit, public și protected. Câmpurile și metodele cu modificator private nu vor fi accesibile în clasa Program.
Dacă clasa Program ar fi fost localizată într-un alt pachet, ar fi avut acces doar la câmpurile și metodele cu modificator public.
Modificatorul de acces trebuie să precede restul definiției unei variabile sau metode.
Încapsulare în Java
Te-ai putea întreba de ce să nu declarăm toate variabilele și metodele cu modificatorul public, astfel încât să fie accesibile din orice punct al programului, indiferent de pachet sau clasă. De exemplu, câmpul age, care reprezintă vârsta. Dacă o altă clasă are acces direct la acest câmp, există șansa ca în timpul execuției programului să primească o valoare incorectă, cum ar fi un număr negativ.
Astfel de modificări ale datelor nu sunt dorite. Sau poate dorim ca unele date să fie disponibile direct, pentru a le afișa în consolă sau pur și simplu pentru a le cunoaște valoarea. În acest sens, este recomandat să restricționăm cât mai mult accesul la date, pentru a le proteja de accesul nedorit din exterior (atât pentru obținerea valorii, cât și pentru modificarea acesteia).
Utilizarea diferiților modificatori garantează că datele nu vor fi distorsionate sau modificate în mod inadecvat. Această ascundere a datelor într-o anumită zonă de vizibilitate se numește încapsulare.
De obicei, în loc să lucrăm direct cu câmpuri, folosim metode de acces. De exemplu:
public class Program{
public static void main(String[] args) {
Person kate = new Person("Kate", 30);
System.out.println(kate.getAge()); // 30
kate.setAge(33);
System.out.println(kate.getAge()); // 33
kate.setAge(123450);
System.out.println(kate.getAge()); // 33
}
}
class Person{
private String name;
private int age = 1;
public Person(String name, int age){
setName(name);
setAge(age);
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return this.age;
}
public void setAge(int age){
if(age > 0 && age < 110)
this.age = age;
}
}
În loc să lucrăm direct cu câmpurile name și age din clasa Person, vom lucra cu metodele care setează și returnează valorile acestor câmpuri. Metodele setName, setAge și altele similare se numesc mutatoare (mutator), deoarece ele modifică valorile câmpurilor. Iar metodele getName, getAge și altele similare se numesc accesorii (accessor), deoarece ele ne permit să obținem valorile câmpurilor.
De asemenea, putem adăuga logică suplimentară în aceste metode. De exemplu, în acest caz, la modificarea vârstei, se efectuează o verificare pentru a se asigura că noua valoare se încadrează în intervalul acceptabil.