Buna ziua! În lecțiile anterioare, ați învățat deja cum să vă declarați propriile clase cu drepturi depline cu metode și câmpuri. În lecția de astăzi, vom vorbi despre Getters și Setters în Java. Acesta este un progres serios, bravo! Dar acum trebuie să vă spun un adevăr neplăcut. Nu ne-am declarat corect orele! De ce? La prima vedere, următoarea clasă nu are greșeli:
Aceste nume provin de la „get” (adică „metoda pentru obținerea valorii unui câmp”) și „set” (adică „metoda pentru setarea valorii unui câmp”). Să vedem cum arată în clasa noastră Cat :
În schimb, producătorul îți oferă o interfață: utilizatorul introduce pur și simplu cifrele corecte, apasă butonul verde de apel, iar apelul începe. Nu-i pasă ce se întâmplă înăuntru cu circuitele și firele sau cum își fac treaba. În acest exemplu, compania limitează accesul la „interiorul” telefonului (date) și expune doar o interfață (metode). Drept urmare, utilizatorul obține ceea ce și-a dorit (abilitatea de a efectua un apel) și cu siguranță nu va sparge nimic în interior. Pentru a consolida ceea ce ați învățat, vă sugerăm să urmăriți o lecție video de la Cursul nostru Java
public class Cat {
public String name;
public int age;
public int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
Dar o face. Imaginează-ți că stai la serviciu și scrie acest curs de pisici pentru a reprezenta pisicile. Și apoi te duci acasă. În timp ce ești plecat, un alt programator sosește la serviciu. Își creează propria clasă principală , unde începe să folosească clasa Cat pe care ați scris-o.
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
}
Nu contează de ce a făcut-o și cum s-a întâmplat (poate că tipul este obosit sau nu a dormit suficient). Altceva contează: clasa noastră actuală Cat permite ca câmpurilor să li se atribuie valori absolut nebunești. Ca rezultat, programul are obiecte cu o stare invalidă (cum ar fi această pisică care are -1000 de ani). Deci ce eroare am făcut când ne-am declarat clasa? Am expus datele clasei noastre. Câmpurile pentru nume, vârstă și greutate sunt publice. Ele pot fi accesate oriunde în program: pur și simplu creați un obiect Cat și orice programator are acces direct la datele sale prin operatorul punct ( . )
Cat cat = new Cat();
cat.name = "";
Aici accesăm direct câmpul de nume și îi setăm valoarea. Trebuie să ne protejăm cumva datele de interferențe externe necorespunzătoare. Ce avem nevoie pentru a face asta? În primul rând, toate variabilele de instanță (câmpurile) trebuie să fie marcate cu modificatorul privat. Private este cel mai strict modificator de acces din Java. Odată ce faci acest lucru, câmpurile clasei Cat nu vor fi accesibile în afara clasei.
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";//error! The Cat class's name field is private!
}
}
Compilatorul vede acest lucru și generează imediat o eroare. Acum câmpurile sunt oarecum protejate. Dar se dovedește că am oprit accesul poate prea strâns: nu puteți obține greutatea unei pisici existente în program, chiar dacă aveți nevoie. Nici aceasta nu este o opțiune. Așa cum este, clasa noastră este în esență inutilizabilă. În mod ideal, trebuie să permitem un fel de acces limitat:
- Alți programatori ar trebui să poată crea obiecte Cat
- Ar trebui să poată citi date de la obiectele existente (de exemplu, să obțină numele sau vârsta unei pisici existente)
- De asemenea, ar trebui să fie posibilă atribuirea valorilor câmpurilor. Dar, făcând acest lucru, ar trebui permise numai valori valide. Obiectele noastre ar trebui să fie protejate de valori nevalide (de exemplu, vârsta = -1000 etc.).
![Getters și setters - 2](https://cdn.codegym.cc/images/article/f516fb67-ab8a-4203-ab14-f42b02e7d04c/512.jpeg)
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
După cum puteți vedea, arată destul de simplu :) Numele lor constau adesea în „get”/“set” plus numele câmpului relevant. De exemplu, metoda getWeight() returnează valoarea câmpului de greutate pentru obiectul pe care este apelat. Iată cum arată într-un program:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
String smudgeName = smudge.getName();
int smudgeAge = smudge.getAge();
int smudgeWeight = smudge.getWeight();
System.out.println("Cat's name: " + smudgeName);
System.out.println("Cat's age: " + smudgeAge);
System.out.println("Cat's weight: " + smudgeWeight);
}
}
Ieșire din consolă:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Acum o altă clasă ( Main ) poate accesa câmpurile Cat , dar numai prin gettere. Rețineți că getterii au modificatorul de acces public, adică sunt disponibili de oriunde în program. Dar cum rămâne cu atribuirea de valori? Pentru asta sunt metodele de setter
public void setName(String name) {
this.name = name;
}
După cum puteți vedea, sunt și simple. Apelăm metoda setName() pe un obiect Cat , trecem un șir ca argument și șirul este atribuit câmpului de nume al obiectului.
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
System.out.println("Cat's original name: " + smudge.getName());
smudge.setName("Mr. Smudge");
System.out.println("Cat's new name: " + smudge.getName());
}
}
Aici folosim atât getter, cât și setter. În primul rând, folosim un getter pentru a obține și afișa numele original al pisicii. Apoi, folosim un setter pentru a atribui un nou nume ("Mr. Smudge"). Și apoi folosim getter-ul încă o dată pentru a obține numele (pentru a verifica dacă s-a schimbat cu adevărat). Ieșire din consolă:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
Deci, care este diferența? Putem atribui în continuare valori nevalide câmpurilor chiar dacă avem setari:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
Ieșire din consolă:
Smudge's age: -1000 years
Diferența este că un setter este o metodă cu drepturi depline. Și spre deosebire de un câmp, o metodă vă permite să scrieți logica de verificare necesară pentru a preveni valori inacceptabile. De exemplu, puteți împiedica cu ușurință atribuirea unui număr negativ ca vârstă:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("Error! Age can't be negative!");
}
}
Și acum codul nostru funcționează corect!
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
Ieșire din consolă:
Error! Age can't be negative!
Smudge's age: 5 years
În interiorul setterului, am creat o restricție care ne-a protejat de încercarea de a seta date nevalide. Vârsta lui Smudge nu a fost schimbată. Ar trebui să creați întotdeauna getters și setters. Chiar dacă nu există restricții cu privire la valorile pe care câmpurile dvs. pot lua, aceste metode de ajutor nu vor face rău. Imaginează-ți următoarea situație: tu și colegii tăi scrieți împreună un program. Creați o clasă Cat cu câmpuri publice. Toți programatorii le folosesc așa cum doresc. Și apoi, într-o bună zi, îți dai seama: "La naiba, mai devreme sau mai târziu cineva ar putea atribui accidental un număr negativ greutății! Trebuie să creăm seteri și să facem toate câmpurile private!" Faci exact asta și spargi instantaneu tot codul scris de colegii tăi. La urma urmei, ei'Câmpurile de pisici direct.
cat.name = "Behemoth";
Și acum câmpurile sunt private și compilatorul aruncă o grămadă de erori!
cat.name = "Behemoth";//error! The Cat class's name field is private!
În acest caz, ar fi mai bine să ascundeți câmpurile și să creați getter și setter de la bun început. Toți colegii tăi le-ar fi folosit. Și dacă ați realizat cu întârziere că trebuie să restricționați cumva valorile câmpului, ați fi putut doar să scrieți cecul în setter. Și codul nimănui nu ar fi rupt. Desigur, dacă doriți ca accesul la un câmp să fie doar „numai în citire”, puteți crea doar un getter pentru acesta. Doar metodele ar trebui să fie disponibile extern (adică în afara clasei dvs.). Datele ar trebui să fie ascunse. Am putea face o comparație cu un telefon mobil. Imaginați-vă că în loc de telefonul mobil închis obișnuit, vi s-a oferit un telefon cu carcasa deschisă, cu tot felul de fire proeminente, circuite etc. Dar telefonul funcționează: dacă încercați cu adevărat și înțepați circuitele, s-ar putea chiar să fiți capabil să efectueze un apel. Dar tu'
![Getters și setters - 3](https://cdn.codegym.cc/images/article/95a95ac4-6577-4851-b006-d9c8fba9cc91/512.jpeg)