Bună! Să dedicăm lecția de astăzi încapsulării și să începem imediat cu exemple :) Principiile încapsulării - 1Aici aveți un aparat obișnuit de sifon . Am o întrebare pentru tine: cum funcționează? Încercați să oferiți un răspuns detaliat: de unde provine ceașca, cum se menține temperatura internă, unde este depozitată gheața, de unde știe aparatul ce sirop să adauge etc.? Probabil că nu aveți răspunsuri la aceste întrebări. Destul de corect, deoarece nu toată lumea folosește astfel de mașini. Nu sunt atât de populare în zilele noastre. Să încercăm să dăm un alt exemplu. Ceva pe care cu siguranță îl folosești de mai multe ori în fiecare zi. Oh, iată o idee! Principiile încapsulării - 2Spune-ne cum este motorul de căutare Googlelucrări. Cum caută exact informații legate de cuvintele pe care le introduceți? De ce anumite rezultate sunt clasate înalt și nu altele? Chiar dacă folosești Google în fiecare zi, sunt șanse să nu știi. Dar nu contează. Nu trebuie să știi asta. Puteți introduce interogări într-un motor de căutare fără a vă gândi cum funcționează. Puteți cumpăra sifon de la o mașină fără să știți cum funcționează. Puteți conduce o mașină fără să înțelegeți cum funcționează un motor cu ardere internă și fără să cunoașteți deloc fizica, chiar și la nivelul școlii elementare. Toate acestea sunt posibile datorită unuia dintre principiile principale ale programării orientate pe obiecte: încapsularea. Citind diverse articole despre programarea orientată pe obiecte (OOP), trebuie să fi dat peste faptul că programarea implică două concepte comune: încapsulare și ascundere . Iar autorii folosesc cuvântul „încapsulare” pentru a însemna un lucru și apoi altul. Vom explora ambii termeni, astfel încât să obțineți o înțelegere completă. În programare, sensul inițial al încapsulării este gruparea datelor, împreună cu metodele care operează pe acele date, într-o singură unitate (adică o „capsulă”). În Java, clasa este unitatea de încapsulare. O clasă conține atât date (câmpuri), cât și metode de lucru cu aceste date.Principiile încapsulării - 3Aceasta poate vi se pare abordarea corectă, dar în alte paradigme de programare, totul este aranjat diferit. De exemplu, în programarea funcțională, datele sunt strict separate de operațiunile pe acestea. În OOP, programele constau din capsule sau clase, care constă atât din date, cât și din funcții pentru lucrul cu acele date. Acum să vorbim despre ascundere . Cum se face că folosim tot felul de dispozitive complexe fără să înțelegem cum sunt organizate sau cum funcționează? Este simplu: creatorii lor ne-au oferit o interfață simplă și convenabilă. La o mașină de sifon, interfața sunt butoanele de pe panou. Apăsând un buton, alegeți dimensiunea cupei. Apăsând pe altul, alegi aroma. Un al treilea este responsabil pentru adăugarea de gheață. Și asta este tot ce trebuie să faci. Organizarea internă a mașinii nu contează. Ceea ce contează este că este proiectat într-un mod care necesită ca utilizatorul să apese trei butoane pentru a obține sifon . Același lucru este valabil și pentru mașini. Nu contează ce se întâmplă înăuntru. Ceea ce contează este că atunci când apăsați pedala dreaptă, mașina se mișcă înainte, iar când apăsați pedala stângă, încetinește. Asta înseamnă ascunderea. Toate „interiorurile” unui program sunt ascunse utilizatorului. Pentru utilizator, aceste informații de prisos, inutile. Utilizatorul are nevoie de rezultatul final, nu de procesul intern. Să ne uităm la Autoclasa ca exemplu:

public class Auto {

   public void go() {

       /* Some complicated things happen inside the car.
       As a result, it moves forward */
   }

   public void brake() {

       /* Some complicated things happen inside the car.
       As a result, it slows down. */
   }

   public static void main(String[] args) {

       Auto auto = new Auto();

       // From the user's perspective,

       // one pedal is pressed and the car accelerates.
       auto.gas();
      
       // The other is pressed, and the car slows down.
       auto.brake();
   }
}
Iată cum arată ascunderea implementării într-un program Java. Este exact ca în viața reală: utilizatorului i se oferă o interfață (metode). Dacă utilizatorul are nevoie de o mașină într-un program pentru a efectua o acțiune, el sau ea apelează doar metoda dorită. Ceea ce se întâmplă în cadrul acestor metode este de prisos. Ceea ce contează este că totul funcționează așa cum trebuie. Aici vorbim despre ascunderea implementării . Pe lângă asta, Java are și ascunderea datelor . Am scris despre asta în lecția despre getters și setters , dar revizuirea conceptului nu va strica. De exemplu, avem o Catclasă:

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!");
   }

  
}
Poate vă amintiți problema cu această clasă din ultima lecție? Dacă nu, să ne amintim acum. Problema este că datele (câmpurile) sale sunt deschise tuturor — un alt programator poate crea cu ușurință o pisică fără nume cu o greutate de 0 și o vârstă de -1000 de ani:

public static void main(String[] args) {

   Cat cat = new Cat();
   cat.name = "";
   cat.age = -1000;
   cat.weight = 0;

}
Poate că puteți urmări îndeaproape dacă unul dintre colegii dvs. a creat obiecte cu stare invalidă, dar ar fi mult mai bine să excludeți chiar și posibilitatea de a crea astfel de „obiecte nevalide”. Principiile încapsulării - 4Următoarele mecanisme ne ajută să realizăm ascunderea datelor:
  1. modificatori de acces ( privat , protejat , implicit pachet )
  2. getters şi setters
De exemplu, putem pune o verificare acolo pentru a vedea dacă cineva încearcă să atribuie un număr negativ vârstei pisicii. După cum am spus mai devreme, autorii diferitelor articole despre încapsulare înseamnă uneori combinarea datelor și metodelor, sau ascunderea lor, sau ambele (combinarea și ascunderea lor). Java are ambele mecanisme (acest lucru nu este neapărat adevărat pentru alte limbaje OOP), deci ultimul sens este cel mai corect. Încapsularea ne oferă câteva avantaje importante:
  1. Control asupra stării corecte a unui obiect. Au fost exemple în acest sens mai sus. Un setter și un modificator privat asigură că programul nostru nu va avea pisici a căror greutate este 0.

  2. Ușurință de utilizare printr-o interfață. Doar metodele sunt lăsate „expuse” lumii exterioare. Metodele de apelare sunt suficiente pentru a obține un rezultat - nu este absolut necesar să aprofundați detaliile modului în care funcționează.

  3. Modificările codului nu afectează utilizatorii. Facem orice și toate modificările în interiorul metodelor. Acest lucru nu afectează utilizatorul metodei: dacă codul corect a fost anterior „auto.gas()” pentru a aplica pedala de accelerație, atunci va continua să fie. Faptul că am schimbat ceva în interiorul metodei gas() rămâne invizibil pentru utilizator: ca și înainte, apelantul primește pur și simplu rezultatul dorit.