Contacte

Ce modificator de acces poate fi aplicat pachetului. Modificatori de acces. Privat, protejat, implicit, public. Controlul accesului și moștenirea

Aici vom încerca să acoperim aproape toate cazurile de utilizare a modificatorilor de acces. Singurele excepții sunt utilizarea lor pentru imbricat ( cuibărit) și intern ( interior), precum și pentru interfețe, deoarece încă nu am luat în considerare aceste subiecte.

Clasele și pachetele utilizate împreună cu modificatorii de acces servesc ca mijloace de încapsulare, adică un mijloc de a ascunde detaliile de implementare în spatele unei interfețe simple.

Modificatorii de acces pot fi aplicați atât claselor, cât și membrilor acestora - câmpuri și metode. Există în total patru modificatori de acces și aici vom oferi o scurtă descriere a acestora, apoi îi vom analiza pe fiecare în detaliu.

  • public- orice componentă declarată ca public, accesibil din orice cod
  • protejat- permite accesul la componenta din pachet si clase de descendenti
  • privat- permite accesul la componentele din cadrul clasei
  • Mod implicit(fără cuvânt cheie) - Permite accesul la componentele din pachet

Clasele moștenite sunt clase moștenite dintr-o clasă. Încă nu am studiat moștenirea.

Acces la cursuri

În mod implicit, clasele de nivel superior sunt disponibile în pachetul în care sunt definite.... Cu toate acestea, dacă clasa de nivel superior este declarată ca public atunci este disponibil peste tot (sau oriunde este disponibil pachetul în sine). Am limitat această declarație la clasele de nivel superior, deoarece clasele pot fi declarate ca membri ai altor clase. Deoarece aceste clase interioare sunt membri ai clasei, ele respectă regulile de control al accesului la membrii clasei..

Accesarea membrilor clasei

Membrii clasei sunt întotdeauna disponibili în corpul clasei. Mod implicit membrii clasei sunt de asemenea disponibili în pachetul în care este definită clasa.

Modificator public

Pentru o clasă care nu este imbricată, poate fi specificat doar unul dintre cele două niveluri de acces posibile: dat Mod implicitși public . Când clasa este declarată ca public, ar trebui să fie singurul public clasa declarată în fișier și numele fișierului trebuie să se potrivească cu numele clasei.

Cum public pot fi declarate clase, câmpuri, metode și constructori.

Modificator protejat

Vom arunca o privire mai atentă asupra acestui modificator în subiectul moștenirii clasei. Dacă moștenirea nu este folosită, atunci acest modificator funcționează, la fel ca modificatorul implicit.

Singurul lucru care poate fi spus pe scurt acum este că componentele declarate ca protejat va avea acces orice clasa de copii din orice pachet sau orice clasă din același pachet.

Cum protejat pot fi declarate câmpuri, metode, constructori, clase imbricate și interfețe imbricate.

protejat .

Modificator privat

Acesta este cel mai restrictiv modificator în ceea ce privește restricția de acces. Articolele declarate ca privat sunt accesibile numai în cadrul aceleiași clase și nimănui din afara clasei.

Cum privat pot fi declarate câmpuri, metode, constructori, clase imbricate și interfețe imbricate.

Clasele și interfețele de nivel superior nu pot fi declarate ca privat .

Practic, modificatorii de acces sunt un subiect simplu, dar vom reveni la ei mai târziu. În timp ce era doar o cunoştinţă. Și acum puțină practică...

Am creat clasele Mod02.java, DefMod.java, ProMod.java și PrvMod.java care aparțin pachetului pro.java.pkg002, precum și clasa PubMod.java, care aparține pachetului pro.java.pkg003. În continuare, voi oferi doar capturi de ecran ale acestor clase și rezultatul programului:

Vom vorbi despre modificatori: ce sunt modificatorii, domeniile, modificatorii pentru clase, câmpuri, metode. Cred că nu va fi plictisitor.

Modificatori în Java Sunt cuvinte cheie care conferă anumite proprietăți unei clase, unui câmp de clasă sau unei metode.

Pentru a indica vizibilitatea unei clase a metodelor și câmpurilor sale, există 4 modificatori de acces:

  • privat membrii clasei sunt accesibili numai în cadrul clasei;
  • pachet-privat sau implicit (implicit) membrii clasei sunt vizibili în interiorul pachetului;
  • protejat membrii clasei sunt disponibili în interiorul pachetului și în clasele derivate;
  • public membrii clasei sunt disponibili pentru toată lumea.

Dacă vă amintiți, la final, când am importat deja clasa Cat, mai aveam o eroare de compilare.

Chestia este că nu am înregistrat niciun modificator de acces la câmpurile și metodele noastre și au o proprietate implicită (membrii clasei sunt vizibili în interiorul pachetului). Pentru a remedia eroarea de compilare pentru codul nostru și, în sfârșit, a-l rula, trebuie să facem publice constructorul și metodele noastre. Apoi pot fi apelate din alte pachete.

Poate începeți să vă întrebați: pentru ce sunt toate acestea? De ce să nu faceți codul vizibil din orice pachet sau clasă, dar trebuie să diferențiați accesul? Aceste întrebări vor dispărea de la sine atunci când va veni timpul să scriem proiecte complexe și greoaie. Acum, când scriem aplicații a căror funcționalitate este limitată la una sau două clase, se pare că nu are sens să limităm ceva.

Imaginați-vă că aveți o clasă care afișează un obiect produs. De exemplu o mașină. Masina poate avea un pret. Ați creat un câmp de preț și multe alte câmpuri, o grămadă de metode care sunt responsabile pentru funcționalitate. Totul pare a fi bine. Mașina dvs. de clasă face parte dintr-un proiect uriaș și toată lumea este fericită. Dar să zicem că cineva, din greșeală sau intenționat, a instanțiat clasa de mașini și a stabilit un preț negativ. Cum poate un produs să aibă un preț negativ? Acesta este un exemplu foarte primitiv și este puțin probabil să se întâmple în viața reală, dar cred că ideea este clară. Uneori trebuie să acordați acces nu direct, ci prin anumite metode. Este posibil ca codul să fie responsabil pentru funcționalitatea altui cod și nu doriți ca cineva să schimbe și să editeze o parte din a dvs. Pentru toate acestea, există o restricție de acces.

Modificatorul de acces pentru constructori, metode și câmpuri poate fi orice. O clasă poate fi doar publică sau implicită și poate exista o singură clasă publică într-un fișier.

Pentru moment, vor fi suficiente despre modificatorii de acces. În articolul „Programare orientată pe obiecte” vom vorbi mai detaliat despre ele, dar acum să vorbim despre alți modificatori dintre care, apropo, sunt mulți.

Acum următorul modificator este static... Poate fi folosit în fața unei metode, câmp și chiar a unei clase atunci când dorim să declarăm o clasă imbricată. În Java, puteți scrie clase în interiorul altor clase, iar dacă modificatorul dinaintea clasei este în interiorul clasei static, atunci o astfel de clasă se numește imbricată, dacă există un alt modificator sau implicit, atunci o astfel de clasă se numește intern. Va exista un articol separat despre clasele imbricate și interioare, deoarece totul nu este atât de simplu acolo.

Modificatorul static din fața unei metode sau a unui câmp indică faptul că nu aparține unei instanțe a acestei clase. Ce înseamnă asta pentru noi? Când am descris un câmp sau o metodă de clasă ca fiind static, acesta poate fi apelat fără a utiliza o instanță a clasei. Adică, în locul acestei construcții: Cat cat = new Cat (); cat.method (), puteți scrie doar Cat.method (). Cu condiția ca metoda să fie declarată statică. Variabilele statice sunt aceleași pentru toate obiectele clasei. Au un singur link.

    Modificatori de clasă publică (

    static int anotherStaticField = 5;

    public static void myStaticMethod () (

    someField = „Câmpul meu”;

    // nonStaticField = ""; eroare de compilare

    // câmpurile nestatice nu pot fi folosite

    // în metode statice

    public void myNonStaticMethod () (

    anotherStaticField = 4; // pot fi folosite câmpuri statice

    // în metode non-statice

    // metoda principală are și un modificator static

    noi Modificatori () .myNonStaticMethod ();

    Modificators.myStaticMethod (); // apelează metode și câmpuri statice

    // prin classname.method

Un alt lucru important de remarcat despre modificatorii statici este că câmpurile statice sunt inițializate la momentul încărcării clasei. Adesea, în diferite tipuri de teste Java, puteți găsi următorul cod:

Întrebare: ce va fi afișat pe consolă? Trebuie reținut că blocul static va fi afișat primul în orice caz. Următorul va fi blocul implicit. Apoi, uită-te la ecranul consolei:

Următorul modificator la care ne vom uita va fi final.

Cred că cuvântul final vorbește de la sine. Aplicând modificatorul final, spui că câmpurile nu pot fi modificate, metodele sunt suprascrise și clasele nu pot fi moștenite (va exista un articol separat despre moștenire). Acest modificator se aplică numai claselor, metodelor și variabilelor (de asemenea, variabilelor locale).

Vom vorbi despre modificatorul final al metodelor și claselor în articolul OOP.

În continuare, vor fi modificatori care nu vor fi foarte clari pentru începători sau pentru cei care citesc această serie de articole de la zero. Și, deși încă nu vă pot explica totul (din cauza faptului că nu cunoașteți materialul însoțitor), tot vă sfătuiesc să vă familiarizați cu ele. Când va veni timpul să folosiți acești modificatori, veți înțelege deja majoritatea termenilor folosiți mai jos.

Modificator sincronizate- indică faptul că metoda poate fi folosită de un singur fir la un moment dat. Deși este posibil să nu vă spună nimic, utilitatea acestui modificator va fi văzută pe măsură ce învățăm despre multithreading.

Modificator tranzitoriu- spune că în timpul serializării obiectului, un câmp ar trebui ignorat. De obicei, aceste câmpuri stochează valori intermediare.

Modificator volatil- folosit pentru multithreading. Când un câmp cu modificatorul volatil va fi folosit și modificat de mai multe fire de execuție, acest modificator asigură că câmpul se va schimba la rândul său și nu va exista confuzie cu acesta.

Modificator nativînainte ca declarația metodei indică faptul că metoda este scrisă într-un alt limbaj de programare. De obicei, în C.

Modificator strictfp- Oferă efectuarea operațiunilor pe numere de tip float și double (virgula mobilă) conform standardului IEEE 754. Sau, mai simplu, garantează că în cadrul unei metode rezultatele calculelor vor fi aceleași pe toate platformele.

Nu am vorbit încă despre modificator abstract... Vă voi spune despre asta pe scurt, pentru că fără cunoștințe de bază ale programării orientate pe obiecte, nu văd nici un rost să vorbesc despre asta.

O clasă care are modificatorul abstract nu poate fi instanțiată. Singurul scop este să fie extins. O clasă abstractă poate conține atât metode abstracte, cât și metode obișnuite.

Vom vorbi mai multe despre modificatorul abstract în articolul OOP.

Aceasta încheie articolul despre modificatori. Despre ei nu s-au spus multe. Dar acest lucru se datorează faptului că nu avem încă concepte OOP. În alte câteva articole, vom extinde modificatorii și vom completa spațiile libere.

Mai întâi, să aruncăm o privire la modificatorii de acces. Sunt doar patru dintre ele:

  • privat membrii clasei sunt accesibili numai în interiorul clasei
  • pachet-privat sau implicit (implicit) membrii clasei sunt vizibili în interiorul pachetului
  • protejat membrii clasei sunt disponibili în interiorul pachetului și în clasele derivate
  • public membrii clasei sunt disponibili pentru toată lumea

În timpul moștenirii, este posibil să schimbați modificatorii de acces către o mai mare vizibilitate.

Modificatorul de acces pentru constructori, metode și câmpuri poate fi oricare, dar cu clasele și blocurile lor nu este atât de simplu. O clasă poate fi doar publică sau implicită și poate exista o singură clasă publică într-un fișier. Un bloc poate avea un singur modificator - implicit.

Modificatori statici, abstracti și finali

Static

  • Se aplică claselor interioare, metodelor, variabilelor și blocurilor logice
  • Variabilele statice sunt inițializate la momentul încărcării clasei
  • Variabilele statice sunt aceleași pentru toate obiectele clasei (aceeași referință)
  • Metodele statice au acces numai la variabile statice
  • Metodele și variabilele statice pot fi accesate prin numele clasei
  • Blocurile statice sunt executate la timpul de încărcare a clasei
  • Metodele non-statice nu pot fi înlocuite ca statice
  • Variabilele locale nu pot fi declarate statice
  • Metodele abstracte nu pot fi statice
  • Câmpurile statice nu sunt serializate (doar la implementarea interfeței Serializable)
  • Numai variabilele de clasă statică pot fi transmise constructorului cu parametri, numite prin cuvântul super (// parametru //) sau acesta (// parametru //)

Abstract

  • Se aplică numai metodelor și claselor
  • Metodele abstracte nu au corp de metodă
  • Este opusul finalului: o clasă finală nu poate fi moștenită, o clasă abstractă trebuie să moștenească
  • O clasă trebuie să fie declarată abstractă dacă:
  1. conţine cel puţin o metodă abstractă
  2. nu oferă o implementare a metodelor abstracte moștenite
  3. nu prevede o implementare a metodelor interfeței a căror implementare a declarat-o
  4. este necesar să se interzică crearea de instanţe ale clasei

Final

  • Câmpurile nu pot fi modificate, metodele sunt înlocuite
  • Clasele nu pot fi moștenite
  • Acest modificator se aplică numai claselor, metodelor și variabilelor (de asemenea, variabilelor locale)
  • Argumentele metodei marcate ca finale sunt doar pentru citire, va apărea o eroare de compilare când se încearcă modificarea
  • Variabilele finale nu sunt inițializate implicit, trebuie să li se atribuie explicit o valoare atunci când sunt declarate sau într-un constructor, în caz contrar - o eroare de compilare
  • Dacă variabila finală conține o referință la un obiect, obiectul poate fi modificat, dar variabila se va referi întotdeauna la același obiect
  • Acest lucru este valabil și pentru matrice, deoarece matricele sunt obiecte, o matrice poate fi schimbată și o variabilă se va referi întotdeauna la aceeași matrice.
  • Dacă clasa este declarată finală și abstractă (concepte care se exclud reciproc), va apărea o eroare de compilare
  • Deoarece o clasă finală nu poate fi moștenită, metodele sale nu pot fi niciodată suprascrise.
Constructor nu poate fi statică, abstractă sau finală

Modificatorii strictfp, tranzitori, volatili, sincronizați, nativi

Strictfp

  • Se aplică metodelor și claselor
  • Oferă operații pe numere flotante și duble (virgulă mobilă) conform standardului IEEE 754

Tranzitoriu

  • Aplicabil numai pentru variabilele la nivel de clasă (variabilele locale nu pot fi declarate ca tranzitorii)
  • Variabilele tranzitorii pot să nu fie finale sau statice.
  • Variabilele tranzitorii nu sunt serializate

Volatil

  • Folosit numai cu variabile
  • Poate fi folosit cu variabile statice
  • Nu este utilizat cu variabilele finale - Valoarea unei variabile declarate ca volatile modificată de un fir este modificată asincron pentru alte fire
  • Folosit în aplicații cu mai multe fire

Sincronizat

  • Se aplică numai metodelor sau părților de metodă
  • Folosit pentru a controla accesul la părți importante ale codului în programele cu mai multe fire

Nativ

  • Folosit numai pentru metode
  • Indică faptul că metoda a fost scrisă într-un alt limbaj de programare
  • Clasele în Java folosesc multe metode native pentru a îmbunătăți performanța și accesul la hardware
  • Este posibil să se transmită/întoarce obiecte Java din metodele native
  • Semnătura metodei trebuie să se termine cu „;”, acolade va provoca o eroare de compilare

Caracteristici în interfețe

  • Metodele sunt întotdeauna publice și abstracte, chiar dacă nu sunt declarate
  • Metodele nu pot fi statice, finale, strictfp, native, private, protejate
  • Variabilele sunt doar finale statice publice, chiar dacă nu sunt declarate
  • Variabilele nu pot fi strictfp, native, private, protejate
  • Poate doar să moștenească (extinde) o altă interfață, nu să implementeze o interfață sau o clasă (implemente).

Să punem toți modificatorii împreună:

Clasă

Clasa interioara

Variabil

Metodă

Constructor

Bloc logic

public

da

da

da

da

da

Nu

protejat

Nu

da (cu excepția cursurilor locale și anonime)

da

da

da

Nu

Mod implicit

da

da

da

da

da

privat

Nu

da (cu excepția cursurilor locale și anonime)

da

da

da

Nu

final

da

Da (și pentru o variabilă locală)

da

Nu

Nu

abstract

da

Da (cu excepția cursurilor anonime)

Nu

da

Nu

Nu

static

Nu

da (cu excepția cursurilor locale și anonime)

da

da

Nu

da

nativ

Nu

Nu

Nu

da

Nu

Nu

tranzitoriu

Nu

Nu

da

Nu

Nu

Nu

sincronizate

Nu

Nu

Nu

da

Nu

Da (doar ca parte a metodei)

volatil

Nu

Nu

da

Nu

Nu

Nu

strictfp

da

da

Nu

da

Nu

Nu

5

Am văzut o discuție pe StackOverflow despre acest subiect, dar nu văd ceva care să mă fi ajutat să înțeleg următorul punct:

Vin dintr-un mediu C++ și recent am început să învăț Java. În C++, când protejat, este folosită doar o subclasă care poate accesa membrul (analog unui câmp în Java).

Există și clase de prieteni în C ++ care pot accesa camerele private / protejate ale clasei, care dau prietenie. Acesta este un pic ca modificatorul de câmp „pachet” în Java (modificatorul de câmp implicit), cu excepția faptului că în C ++, prietenia oferă acces tuturor membrilor privați, dar în Java, accesul de la clase dintr-un pachet este specific clasei camp.

Ceea ce nu pot să-mi dau seama, presupunând că vreau doar să ofer acces la subclase, este ceea ce pot face în C ++ declarând membri protejați într-o clasă care nu „oferă” prietenii.

Dar în Java nu știu cum să fac asta, pentru că cu ajutorul unui modificator de câmp „protejat” - ofer și acces la toate clasele din pachet. Singurul mod în care îl găsesc este să declar un câmp protejat și să izolez clasa din pachetul său.

De aici concluzionez că gruparea claselor într-un singur pachet ar trebui făcută pe baza „prieteniei” dintre clase. Este acesta într-adevăr factorul principal atunci când grupați pachete?

Un alt lucru pe care nu îl înțeleg, în Java, presupunând că am două câmpuri în clasa A: b, c. Vreau să-i dau lui B acces la b, dar nu la și vreau să îi dau lui C acces la c, dar nu la b. iar la „Pace” vreau ca b, c să se ascundă. Cum pot face acest lucru? Presupun că B, C ar trebui să fie în același pachet ca A. dar declarând b, c cu pachet cu modificatorul I permit accesul lui B, C atât la b cât și la. Există vreo modalitate în Java de a face asta?

Sper să avem o explicație la această întrebare

11

O întrebare mai bună, dacă este mai puțin utilă, va fi mai restrânsă și mai specifică. Întrebarea generală „totul despre confidențialitate în Java și C ++ și cum diferă” este mai mult decât prea largă. Puteți pune o întrebare mai specifică despre o problemă mai specifică? - Yakk 04 mar 15 2015-03-04 16:38:58

  • 4 raspunsuri
  • Triere:

    Activitate

2

În C ++, când se utilizează securitatea, doar subclasa poate accesa elementul (analog cu un câmp din Java).

Specificatorii de acces sunt, de asemenea, pentru funcțiile/metodele membre, nu doar pentru variabilele membre.

În C++ există și clase „prieten” care pot accesa membrii private/protejați ale clasei, ceea ce dă „prietenie”. Acesta este un pic ca modificatorul de câmp „pachet” din Java (modificatorul de câmp implicit), cu excepția faptului că în C ++, prietenia oferă acces tuturor membrilor privați, dar în Java, accesul din clasele din același pachet este specific pentru câmpul clasei.

Nu există doar cursuri de prieteni, ci și funcții.

Este adevărat că accesarea părților private Java este similară, dar nu este o înlocuire completă. Mai bine să spunem că aceste două funcții au subset problemele pe care le rezolvă. Sunt probleme care pot fi rezolvate de un prieten, dar nu de un pachet privat și invers.

Ceea ce nu mi-am putut da seama, presupunând că vreau doar să ofer acces la subclase, este ceea ce pot face în C ++ declarând utilizatorii protejați într-o clasă pe care prietenia nu o „oferă”.

Dar în Java, nu știu cum pot face asta,

Răspuns: Nu poți.

deoarece cu ajutorul unui modificator de câmp „protejat” - ofer și acces la toate clasele din pachet.

Singura modalitate pe care o pot găsi este să declar un câmp protejat și să izolați clasa în pachetul său.

Tehnic, da. Dar asta creează alte probleme. Clasa dvs. nu va mai putea accesa părțile pachetului privat din pachetul anterior. Să presupunem că BaseClass a fost la com.example.one. Îl vei muta în com.example.two. Acum nu va mai putea accesa alte pachete de clasă privată com.example.one.

Este acesta într-adevăr factorul principal atunci când grupați pachete?

Da, Java este conceput astfel. Poti incerca lupta cu regulile limbii dar este o bătălie pierdută în orice limbaj de programare.

Un alt lucru pe care nu îl înțeleg în Java, presupunând că am două câmpuri în clasa A: b, c. Vreau să-i dau lui B acces la b, dar nu la și vreau să îi dau lui C acces la c, dar nu la b. iar în „Lumea” vreau ca b, c să se ascundă. Cum pot face acest lucru?

Nu se poate face într-un mod curat (curat, vreau să spun: fără hack-uri care ar necesita să verificați stiva de apeluri în timpul execuției și să aruncați excepții).

Dacă sunteți îngrijorat de acest scenariu deoarece dezvoltați un API public, o soluție low-tech care de obicei funcționează excelent este să creați unul sau mai multe pachete * .internal și să documentați clar faptul că acestea nu ar trebui utilizate în codul clientului.

1

Sunt o grămadă de întrebări împreună...

Dar în Java, nu știu cum pot face acest lucru, deoarece în virtutea utilizării unui modificator de câmp „protejat” - ofer și acces la toate clasele din pachet.

Într-adevăr, nu există nicio modalitate de a oferi acces doar la subclase, dar nu și la clase din același pachet. A fost o decizie de design luată cu secole în urmă...

Singurul mod în care îl găsesc este să declar un câmp protejat și să-l izolez în pachetul meu.

Acest lucru este corect din punct de vedere tehnic, deși va fi de puțin folos. Încadrarea claselor este pentru gruparea claselor înrudite, unde „frații” înseamnă „clase care îndeplinesc o anumită relație”, adică aparțin aceluiași caz de utilizare, aparțin aceluiași nivel arhitectural, sunt în aceleași entități etc.

De aici concluzionez că gruparea claselor într-un singur pachet ar trebui făcută pe baza „prieteniei” dintre clase. Este acesta într-adevăr factorul principal atunci când grupați pachete?

Cred că am răspuns deja la acest lucru în paragraful anterior: ambalajul este pentru gruparea claselor conexe după niște criterii specifice.

Pentru clasele dvs. A, B și C, de exemplu cu atribute:

Cred că B, C ar trebui să fie ambele în același pachet, A declarând b, cu modificatorul de ambalare, îi las pe B, C să acceseze atât b, cât și k. Există o modalitate în Java de a face acest lucru?

Răspunsul este nu, nu există o modalitate ușoară și curată de a face acest lucru. Ați putea realiza acest lucru cu niște hack-uri sau tehnici mai avansate, dar din nou, aceasta a făcut parte din deciziile luate de designerii de limbi cu mult timp în urmă...

0

Răspuns scurt: nu există nicio modalitate de a face acest lucru.

Dacă sunteți îngrijorat de intruziunea de la injectarea clienților de clasă într-un pachet pentru a obține acces neautorizat, puteți muta codul sensibil într-un pachet separat și faceți pachetul sigilat într-un borcan pe care îl trimiteți la: http://docs.oracle. com/javase/tutorial /deployment/jar/sealman.html

1

Se presupune implicit că toate clasele dintr-un pachet „se cunosc” între ele (pentru că au fost scrise de aceeași persoană/companie/organizație). În acest fel, fie nu au acces la câmpurile protejate, fie dacă o fac, știu cum să o facă corect.

Se presupune că clasele din același pachet sunt mai legate între ele decât este părintele cu clasa derivată, deoarece clasa derivată ar putea fi de fapt scrisă de altcineva. Așa că au decis că protecția privată era mai mult limitată decât protejată.

Deci, cred că nu trebuie să vă faceți griji cu privire la modul în care clasele din același pachet pot accesa câmpurile reciproce. În general, pur și simplu nu folosesc această funcție, decât atunci când scriu iteratoare.

Dacă aveți două câmpuri, le puteți face clase interioare, astfel încât să aibă acces la câmpuri private (din nou, logic: dacă o clasă se află în interiorul unei alte clase, ea știe despre semantica acelei clase) și să poată expune acel acces la derivatele lor. clase prin metode protejate.

Bineînțeles că puteți veni cu un protocol complex de schimb de jetoane pentru a face acest câmp accesibil doar instanțelor B/C, dar ar fi o suprasolicitare minunată și un alt obiect poate folosi în continuare reflectarea pentru a accesa toți membrii privați dacă nu îl dezactivați. folosind politici de securitate, ceea ce de obicei nu este cazul, dar din nou, politicile de securitate sunt hotărâte în cele din urmă de proprietarul JVM-ului.

Deci, în cele din urmă, modalitatea preferată de a face ceea ce spuneți în Java este fie să le puneți în același pachet, fie să scrieți B și C ca clase interioare ale lui A, astfel încât să poată accesa direct membrii privați ai lui A și să le expună clasele derivate.

Public class A (public static abstract class B (protejat Whatever getWhatever (A a) (return ab;) protected void setWhatever (A a, Whatever value) (ab = value;)) public static abstract class C (protejat Whatever getWhatever (A) a) (return ac;) protected void setWhatever (A a, Indiferent de valoare) (ac = valoare;)) private Indiferent b; privat Indiferent c;)

încă o dată, te gândești mereu că cursurile din același pachet nu vor face niciodată nimic rău.

Ultima actualizare: 03.10.2019

Toți membrii unei clase - câmpuri, metode, proprietăți - toți au modificatori de acces... Modificatorii de acces vă permit să setați un domeniu valid pentru membrii clasei. Adică, modificatorii de acces definesc contextul în care poate fi utilizată o anumită variabilă sau metodă. În subiectele anterioare, am întâlnit-o deja când am declarat că câmpurile de clasă sunt publice (adică cu modificatorul public).

Următorii modificatori de acces sunt utilizați în C #:

    public: o clasă publică, publică sau un membru al unei clase. Un astfel de membru al clasei este accesibil de oriunde în cod, precum și din alte programe și ansambluri.

    privat: o clasă privată sau membru al unei clase. Reprezintă exact opusul modificatorului public. O astfel de clasă privată sau membru al clasei este accesibil numai din codul din aceeași clasă sau context.

    protejat: un astfel de membru al clasei este accesibil de oriunde în clasa curentă sau în clasele derivate. Cu toate acestea, clasele derivate pot fi localizate în alte ansambluri.

    intern: o clasă și membrii unei clase cu un modificator similar sunt accesibile de oriunde în cod în același ansamblu, dar nu este disponibil pentru alte programe și ansambluri (cum este cazul modificatorului public).

    intern protejat: combină funcționalitatea a doi modificatori. Clasele și membrii clasei cu acest modificator sunt disponibili din ansamblul curent și din clasele derivate.

    private protected: un astfel de membru al clasei este accesibil de oriunde în clasa curentă sau în clasele derivate care sunt definite în același ansamblu.

Putem seta în mod explicit modificatorul de acces, de exemplu:

Clasă privată protejată State (intern int a; protected void Print () (Console.WriteLine ($ "a = (a)");))

Sau putem sări peste specificarea:

Stare clasă (int a; void Print () (Console.WriteLine ($ "a = (a)");))

Dacă nu este definit niciun modificator de acces pentru câmpuri și metode, modificatorul privat este utilizat pentru acestea în mod implicit.

Clasele și structurile declarate fără un modificator au acces intern implicit.

Toate clasele și structurile care sunt definite direct în spațiile de nume care nu sunt imbricate în alte clase pot avea doar modificatori publici sau interni.

Să ne uităm la un exemplu și să creăm următoarea clasă State:

Clasa publică State (// este aceeași cu private int defaultVar; int defaultVar; // câmpul este accesibil numai din clasa curentă private int privateVar; // accesibil din clasa curentă și clasele derivate care sunt definite în același proiect protejat private int protectedPrivateVar; // disponibil din clasa curentă și din clasele derivate protected int protectedVar; // disponibil oriunde în proiectul curent internal int internalVar; // disponibil oriunde în proiectul curent și din clasele moștenite din alte proiecte protected internal int protectedInternalVar; // disponibil oriunde în program, precum și pentru alte programe și ansambluri public int publicVar; // are un modificator implicit private void defaultMethod () => Console.WriteLine ($ "defaultVar = (defaultVar)"); / / metoda este accesibilă numai din clasa curentă private void privateMethod () => Console.WriteLine ($ "privateVar = (privateVar)"); // accesibilă din clasa curentă și clasele derivate care sunt definite în același paragraf protected private void protectedPrivateMethod () => Console.WriteLine ($ "protectedPrivateVar = (protectedPrivateVar)"); // accesibil din clasa curentă și clasele derivate protected void protectedMethod () => Console.WriteLine ($ "protectedVar = (protectedVar)"); // disponibil oriunde în proiectul curent intern void internalMethod () => Console.WriteLine ($ "internalVar = (internalVar)"); // disponibil oriunde în proiectul curent și din clasele moștenite în alte proiecte protected internal void protectedInternalMethod () => Console.WriteLine ($ "protectedInternalVar = (protectedInternalVar)"); // disponibil oriunde în program, precum și pentru alte programe și ansambluri public void publicMethod () => Console.WriteLine ($ "publicVar = (publicVar)"); )

Deoarece clasa State este declarată cu modificatorul public, aceasta va fi accesibilă de oriunde în program, precum și din alte programe și ansambluri. Clasa State are cinci câmpuri pentru fiecare nivel de acces. Plus o variabilă fără modificator, care este privată în mod implicit.

Există, de asemenea, șase metode care vor afișa pe ecran valorile câmpurilor de clasă. Vă rugăm să rețineți că, deoarece toți modificatorii vă permit să utilizați membrii clasei în cadrul acestei clase, atunci toate variabilele de clasă, inclusiv cele private, sunt disponibile pentru toate metodele sale, deoarece toate sunt în contextul clasei State.

Acum să vedem cum putem folosi variabilele clasei noastre în program (adică în metoda Main a clasei Program), dacă clasele State și Program sunt în același proiect:

Class Program (static void Main (string args) (State state1 = new State (); // nu vom putea atribui valoarea variabilei defaultVar, // deoarece are un modificator privat și clasa Program nu vede it // Și mediul va sublinia drept incorect state1.defaultVar = 5; // Eroare, nu puteți obține acces // Același lucru este valabil și pentru variabila privateVar state1.privateVar = 5; // Eroare, nu puteți obține acces // atribui valoarea variabilei protectedPrivateVar nu va funcționa, // deoarece clasa Program nu este o subclasă a clasei State state1.protectedPrivateVar = 5; // Eroare, nu puteți obține acces // atribuirea valorii variabilei protectedVar va eșua. , // deoarece clasa Program nu este o subclasă a clasei State state1.protectedVar = 5; // Eroare, nu puteți obține acces // variabila internalVar cu modificatorul intern este accesibilă de oriunde în proiectul curent // prin urmare, atribuiți-i în siguranță valoarea state1.internalVar = 5; // variabila protectedInternalVar este, de asemenea, accesibilă de oriunde în starea curentă a proiectului1.protectedInternalVar = 5; // publicVar este disponibil public state1.publicVar = 5; ))

Astfel, am putut seta doar variabilele internalVar, protectedInternalVar și publicVar, deoarece modificatorii lor ne permit să le folosim în acest context.

Situația este similară cu metodele:

Program de clasă (static void Main (șir argumente) (State state1 = new State (); state1.defaultMethod (); // Eroare, nu poate fi accesată state1.privateMethod (); // Eroare, nu poate fi accesată state1.protectedPrivateMethod () ; // Eroare, nu puteți obține acces state1.protectedMethod (); // Eroare, nu puteți obține acces state1.internalMethod (); // norme state1.protectedInternalMethod (); // norme state1.publicMethod (); // norme ))

Aici, doar trei metode erau disponibile pentru noi: internalMethod, protectedInternalMethod, publicMethod, care au modificatorii interni, protejați interni și, respectiv, public.

Datorită unui astfel de sistem de modificatori de acces, este posibilă ascunderea unor aspecte ale implementării clasei de alte părți ale programului.

În ciuda faptului că modificatorii publici și interni sunt similari în acțiunea lor, au o mare diferență. Clasele și membrii unei clase cu modificatorul public vor fi, de asemenea, disponibili pentru alte programe dacă clasa dată este plasată într-o bibliotecă dll dinamică și apoi utilizată în aceste programe.



Ți-a plăcut articolul? Împărtășește-l