Java și C / Linux Tweet

Ascunderea și încapsularea în C ++

am auzit despre încapsularea informațiilor din limbile Orientate spre obiecte și în C ++. Să vedem aici ceea ce constă în și unele „trucuri” pe care le putem face în cazul specific al C ++ și care nu vin de obicei în cărțile acestei limbi (deși în cărți despre modelele de design).

Punctele pe care le vom vedea sunt:

  • atac al trampler-urilor dintr-o clasă
  • Importanța Lanegnalesulaționali pentru a compila în C ++
  • Încapsulare prin interfețe

Încapsularea atributelor unei clase

În primul rând, ar trebui să fie clar că încapsularea, la fel ca orice bun Obiceiul de programare (deoarece nu scoate, comentariul etc.) este util pentru codul care mai poate fi reutilizat sau modificat, de către alte persoane sau de sine. Dacă fac un program marțian și niciodată nu intenționez să o ating din nou, nu contează cât de mult o fac cu gouts și fără să comentăm în timp ce mă găsesc în timp ce fac și funcționează. Voi plăti acest „păcat” dacă în două luni mă pot gândi la îmbunătățirea acestuia sau vreau să reutilizeze ceva din codul său pentru un alt program.

Eu comentez acest lucru deoarece încapsularea, a condus la capătul său, așa cum este cazul punctului de interferență, face ca programarea să fie mai complicată (trebuie să faceți mai multe clase). Acest efort este recompensat numai dacă codul este foarte mare (evitând recilții inutile) sau va fi refolosit în viitor (putem extrage clase cu mai puține dependențe din alte clase). Asta a spus, hai să mergem la subiect.

Orice curs de orientare a obiectelor ne spune că este mai bine să punem atributele unei clase protejate sau private (niciodată publice) și să le accesați prin metode publice pe care le punem în clasă. Să vedem motivul. Să presupunem, de exemplu, că cereți un program care vă permite să aduceți o listă de persoane cu datele de naștere. Printre altele, am decis să ne facem clasa noastră de date cu câteva metode minunate după cum urmează.

Clasa Data: Public:
Int Anho; // anho cu patru cifre, de exemplu. 2004
int luna; // luna, de la 1 la 12
INT; // ziua, de la 1 la 31
VOD Methodomaravilloso1 ();
VOID Methodomaravillos2 ();
};

Am făcut deja clasa. Acum facem restul codului și în câteva mii de linii de cod folosim direct lucrurile așa.

Data unității;
inaccha.anho = 2004;
inaccha.mes = 1;
inaccha.dia = 25;

În cele din urmă am terminat programul nostru și totul funcționează excelent. Câteva zile mai târziu, ei ne spun că programul va păstra tropesele mii de oameni și care iau multe dosare, decât să vadă dacă putem face ceva pentru ao remedia. Wow, stocăm o dată cu trei numere întregi. Dacă folosim formatul celor mai multe computere, în care data este numărul de secunde din 1 ianuarie 1970 (care ne returnează funcția de timp ()), este suficient cu un număr întreg.

Total, ce mâini sunt schimbate, a schimbat clasa noastră, astfel încât să aibă următoarele:

Clasa Data:

/ * Comentată de Porineficial
Intanho; Inmedite;
Intia; * /

longnumesseconds;

Vidmetodomaravilloso1 ();
VOID Methodomaravillos2 ();
};

este deja făcut ușor. Acum trebuie doar să treceți prin tropedele de mii de linii de cod prin schimbarea sarcinilor și a citirilor la cele trei numere întregi anterioare de către noul lungime.

ar fi fost mult mai bine dacă am fi făcut aceste trei numere întregi și metode protejate pentru a le accesa. Ceva de genul ăsta

clasa de clasă:

VOID TOMAFECHA (INT ANHO, INT LUNI, INTDIA);
Int Dameanho ();
Int Damemes ();
Int Damedia ();
vid Metodomaravilloso1 ();
VOID Methodomaravillos2 ();
Protejat:
Int Anho; // anho cu patru cifre, de exemplu. 2004
int luna; // luna, de la 1 la 12
INT; // Ziua, de la 1 la 31
};

Dacă acum trebuie să facem aceeași schimbare, schimbați atributele protejate. Metodele Tomaxxx () și Damexxx () sunt menținute în termeni de parametri și valoarea returnată, dar codul său intern este modificat pentru a face anul, luna și ziua într-o lungă secundă și cu susul în jos. Restul codului nu trebuie să-l atingă deloc.

Este chiar mai bine să faceți atributele private care sunt protejate. Făcându-le protejați, clasele fiice (cei care moștenesc de la data) pot accesa direct aceste atribute. Când facem schimbarea pentru o lungă perioadă de timp, trebuie să schimbăm și codul claselor de fiice. Dacă atributele sunt private și forțăm cursurile de fiice să le acceseze prin metode, nu va trebui să schimbăm codul acestor clase de fiice.

Accesul prin metode este mai puțin eficient decât să îl faceți direct, deci, deși în urma principiului ascunderii, este mai bine să faceți atribute private, prin eficiență, în unele cazuri, este mai bine să le faceți protejați (sau chiar publicului ) să riscă să schimbe mai multe linii de cod în caz de schimbare.

Sfaturi:
ori de câte ori este posibil atributele unei clase private.

Importanța încapsulării în C ++

cu ceea ce este numărat până acum, evităm Trebuie să schimbe codul în cazul schimbării parametrilor.

În cazul concret al C ++ există o mică problemă suplimentară. Este destul de normal să faceți clasele să definească prin intermediul a două fișiere. În cazul clasei de date, am avea o dată.h cu definiția clasei și o dată.cc (sau .cpp) cu codul metodelor de clasă. Când vrem să folosim clasa de date, de obicei facem #include-ul nostru < date.h >.

orice proces eficient de compilare (cum ar fi Linux face utilitate și cred că Visual C ++) este suficient pentru a recompila numai acele fișiere care trebuie recompilate. Asta este, dacă avem deja proiectul compilat și jucăm un fișier, compilatorul va compila doar acel fișier și toți cei care depind de el. Aceste caracteristici sunt foarte importante în proiecte mari (cu multe fișiere și multe linii de cod), pentru a salva timpul de compilare de fiecare dată când facem o modificare (am lucrat la proiecte pe care mi le-a luat să compil de la zero în jurul a 4 ore).

Care este problema? Problema este că, dacă decidem, de exemplu, schimbați din nou atributul privat al clasei de date pentru altceva, trebuie să atingem data de fișier.h. Acest lucru va face toate fișierele care fac #include < data. Care la rândul său nu este #include data. Ei bine, așa mai departe.

Soluția este evidentă, cât mai puțin posibilă la data. H, în special variabilele #define și globale care nu sunt necesare pentru a vedea din alte clase.

De exemplu, clasa noastră de dată ar putea avea unele #define să indice care este numărul minim și maxim de lună. Este mai bine să plasați aceste #define la data. CC în loc de data. H, dacă cineva trebuie să le vadă.

// acest cel mai bun în .cc decât în .h
#define mes_minimo 1
#define mes_maximo 12
sfaturi:
ori de câte ori este posibil, punere # definește, tipuri de definiție, constante globale etc., în interiorul DelficHerro.cc

încapsulare prin interfețe

Avem un lucru rămas. De ce trebuie să recompilim multe lucruri dacă schimbăm un atribut privat al clasei? Idealul ar fi acela de a putea schimba lucrurile interne ale clasei, fără a fi nevoie să recompilim nimic altceva, la urma urmei, atributul este privat și nimeni nu o folosește direct.

Este destul de comun în programarea orientată pe obiecte Utilizarea interfețelor pentru a face clasele depind unul de celălalt. În cazul C ++, utilizarea interfețelor este, de asemenea, utilă pentru a evita recilții inutile.

O interfață nu este mai mare decât o clasă în care sunt definite metodele publice necesare, dar nu sunt implementate. Apoi, clasa concretă pe care vrem să o facem de la acea interfață și să-i implementeze metodele.

În cazul nostru, putem face o clasă de interfață, cu metode publice virtuale virtuale (fără cod). Apoi, clasa de date moștenește de la interfață și implementează aceste metode.

în fișierul de interfață. Virtual Int Dameanho () = 0;
Virtual Int Damemes () = 0;
Virtual Int Damedia () = 0; Virtual Vold Methodomaravilloso1 () = 0; Virtual Vold Metodomaravillos2 () = 0;
};

în acest moment, nu ar exista nici măcar o interfață. CC

Clasa de date este încă aceeași, dar moștenită din interfață.

#include < interfațăfea.h >

clasa Data: Interfață publică> Public:
Void Tomafa (int anho, int luna, intdia);
Int Dameanho ();
Int Damemes ();
Int Damedia ();
vid Metodomaravilloso1 ();
VOID Methodomaravillos2 ();
Protejat:
Int Anho; // anho cu patru cifre, de exemplu. 2004
int luna; // luna, de la 1 la 12
INT; // Ziua, de la 1 la 31
};

Acum, oricine are nevoie de o dată, trebuie să aibă un pointer de interfață în loc de până în prezent. Cineva va instala data și o va păstra în acest indicator. Adică am putea face ceva de genul ăsta

#include < data.h >
#include < interfață. >
…Interfață infectată * unitate = nulă;

UNDOO = noua dată ();
inaccha- > Tomacca (2004, 1, 27);

Ștergerea unității;
inaccha = null;

Dacă arătăm puțin, nu am rezolvat încă nimic, cu excepția cazului în care este complicat problema. Cel care are acest cod trebuie să facă acum #include atât interfața.h și data.h. Dacă atingem ceva la zi. H, acest cod va fi recomptit.

Acest cod are nevoie #include < data.h > pentru a putea face data de data. Trebuie să căutați cum să evitați acel nou. De obicei, este, de asemenea, destul de obișnuită pentru a face o clasă (sau pentru a folosi aceeași interfață dacă limba o permite, așa cum este cazul C ++) pentru a pune o metodă statică pe care nouă și să o returnați.

În cazul Java, prin punerea acestei metode, nu am mai avea o interfață, ci o clasă. Efectuarea datei de informare a datei ne limitează să nu moștenim din altceva (Java nu acceptă moșteniri multiple). Dacă acest lucru este admisibil, putem să o facem așa. Dacă avem nevoie de acea dată moștenit de la o altă clasă, în loc să punem metoda statică în interfață, trebuie să facem un al treilea generator separat cu această metodă statică.

În exemplul nostru C ++, clasa de interfață ar fi lăsată.

interfața de clasă
{
public:

staticinterfaceface * damenuevafecha ();

Vildometare virtuală (Intanho, Intanho, Inty Day) = 0; Virtual Int Dameanho () = 0;
Virtual Int Damemes () = 0;
Virtual Int Damedia () = 0; Virtual Vold Methodomaravilloso1 () = 0; Virtual Vold Metodomaravillos2 () = 0;
};

Acum avem nevoie de o interfață. cc. În interiorul lui vom avea

#include <. 70D99B01CF „

Data.
}

Codul care a folosit anterior pointerul de interfață ar fi acum

#include < interfață. >

interfață * neaccha = null;

inaccha = Interfața infectată :: Damenuecha ();
inaccha- > Tomacca (2004, 1, 27);

Ștergerea unității;
inaccha = null;

după cum vedem, numai #includa de interfațăfeafe.h și acest lucru nu include data.h (nu interfață, nu .h). Am făcut ca acest cod să nu se vede la curent. Acum putem juca fără o privire la data. H, pe care acest cod nu trebuie să fie recompilat.

Un avantaj suplimentar este că puteți schimba data de dată pentru o altă dată de clasă2 la Runtime. Ar fi suficient să puneți un atribut static în interfață pentru a indica data de clasă pe care o dorim și să facem metoda Damenenuevacaha () instantaneu și returnează unul sau altul în funcție de atributul respectiv.

Sfat:
Utilizați interfețele Paraquelas Clasque plânge pe care le puteți schimba del Deproyectoo de Developy de dezvoltare.

Acest mecanism obține o instanță a unei clase printr-o metodă statică și O interfață, pentru a nu depinde de clasa specifică, cred că în lumea modelelor de design este modelul fabricii.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *