Perché abbiamo bisogno di variabili private?


210

Perché abbiamo bisogno di variabili private nelle classi?

Ogni libro sulla programmazione che ho letto dice che questa è una variabile privata, ecco come la definisci ma si ferma lì.

La formulazione di queste spiegazioni mi è sempre sembrata una crisi di fiducia nella nostra professione. Le spiegazioni sono sempre sembrate come se altri programmatori fossero fuori per incasinare il nostro codice. Tuttavia, ci sono molti linguaggi di programmazione che non hanno variabili private.

  1. Cosa impediscono le variabili private?

  2. Come decidi se una determinata proprietà deve essere privata o no? Se per impostazione predefinita ogni campo DOVREBBE essere privato, allora perché ci sono membri di dati pubblici in una classe?

  3. In quali circostanze una variabile dovrebbe essere resa pubblica?


9
La tua domanda sembra molto indipendente dal linguaggio, ma l'hai taggata come java e c ++. Se sei interessato a prospettive al di fuori di quelle due lingue, probabilmente dovresti dirlo.
James,

8
Per la cronaca, la creazione di un metodo privato non aumenta la "sicurezza". Altre parti dell'applicazione possono comunque accedere ai membri privati ​​tramite reflection.
kba,

3
L'uso e la differenza di variabili pubbliche e private, e il motivo per cui le abbiamo, possono essere comprese solo nel contesto dei principi generali orientati agli oggetti. Non può essere compreso separatamente. Probabilmente devi guardarlo da quella prospettiva, le cose potrebbero diventare più chiare.
Nazar Merza,


3
Se prendi qualcuno che usa una cintura di sicurezza nella sua auto, dovresti portare via la patente, dal momento che ovviamente non si fidano delle proprie capacità di guidare.
gnasher729,

Risposte:


307

Non è tanto una questione di fiducia, quanto piuttosto una gestione della complessità.

È possibile accedere a un membro pubblico al di fuori della classe, che per considerazioni pratiche significa "potenzialmente ovunque". Se qualcosa va storto in un campo pubblico, il colpevole può essere ovunque, quindi per rintracciare il bug, potresti dover esaminare un sacco di codice.

Un membro privato, al contrario, è accessibile solo dall'interno della stessa classe, quindi se qualcosa non va, di solito c'è solo un file sorgente da guardare. Se hai un milione di righe di codice nel tuo progetto, ma le tue classi sono tenute piccole, questo può ridurre il tuo sforzo di tracciamento dei bug di un fattore 1000.

Un altro vantaggio è legato al concetto di "accoppiamento". Un membro pubblico mdi una classe Ache viene utilizzata da un'altra classe Bintroduce una dipendenza: se si cambia min A, è necessario controllare anche gli usi di min B. Peggio ancora, nulla in classe Ati dice dove mviene utilizzato, quindi devi cercare nell'intera base di codice; se è una libreria che stai scrivendo, devi anche assicurarti che il codice all'esternoil tuo progetto non si interrompe a causa del tuo cambiamento. In pratica, le biblioteche tendono a rimanere con le firme dei metodi originali il più a lungo possibile, non importa quanto dolorose, e quindi introducono un blocco di interruzioni delle modifiche con un aggiornamento della versione principale. Con i membri privati, al contrario, puoi escludere subito le dipendenze - non sono accessibili dall'esterno, quindi tutte le dipendenze sono contenute all'interno della classe.

In questo contesto, "altri programmatori" includono i tuoi sé futuri e passati. È probabile che tu sappia ora che non dovresti fare questa cosa X con la tua variabile Y, ma sei sicuro di aver dimenticato tre mesi lungo la strada quando un cliente ha urgentemente bisogno di implementare alcune funzionalità e ti chiedi perché fare X break Y in modi oscuri.

Quindi, per quanto riguarda quando dovresti rendere le cose private: direi di rendere tutto privato per impostazione predefinita, quindi esporre solo quelle parti che devono assolutamente essere pubbliche. Più puoi rendere privato, meglio è.


24
+1 per essere al centro del problema, anche se ho trovato personalmente il mio codice più facile da mantenere quando ho smesso di passare attraverso i cerchi solo per garantire che una variabile utilizzata di frequente rimanga privata. Sicuramente potrebbe verificarsi un errore in futuro, ma sono 60 le righe di codice in meno da esaminare e meno variabili e funzioni da avviare;)
Jeffrey Sweeney,

48
Il santo graal dell'informatica moderna sta mantenendo bassa la complessità.

1
Mi piace sempre dire che parte del debug non consiste solo nel guidare direttamente "ciò che è andato storto", ma nel seguire la procedura rotonda per capire "cosa non è andato storto" e focalizzare la mia indagine su ciò che resta. Se riesco a far sì che il compilatore mi assista con strumenti come variabili private per definire "ciò che non può essere accaduto", ciò mi fa risparmiare un sacco di tempo. Solo nei rari casi in cui provo che ciò che è andato storto non può essere accaduto, devo scavare in ipotesi più spaventose, come forse un sovraccarico di buffer che sovrascrive i miei dati privati.
Cort Ammon,

2
Esattamente quello. Quando le persone sentono "nascondere le informazioni", pensano che dovrebbero usare variabili private per cose come chiavi di crittografia, credenziali del database, ecc.
Wayne Werner,

2
@AdamZerner vedi "Dillo, non chiedere" ( martinfowler.com/bliki/TellDontAsk.html ) di avere getter / setter in primo luogo - ma altrimenti sì, perché dovresti essere libero di cambiare la rappresentazione interna del valore in qualsiasi momento desideri. Come sempre, ci sono eccezioni ... (ad es. DTO)
doppio

111

Le variabili private aiutano a impedire alle persone di dipendere da determinate parti del codice. Ad esempio, supponiamo che tu voglia implementare una struttura di dati. Desideri che gli utenti della tua struttura dati non si preoccupino di come la hai implementata, ma piuttosto utilizzi l'implementazione attraverso la tua interfaccia ben definita. Il motivo è che se nessuno dipende dalla tua implementazione, puoi cambiarla quando vuoi. Ad esempio, è possibile modificare l'implementazione back-end per migliorare le prestazioni. Qualsiasi altro sviluppatore che dipendesse dalle tue implementazioni si romperà, mentre gli utenti dell'interfaccia andranno bene. Avere la flessibilità di cambiare le implementazioni senza influenzare gli utenti della classe è un enorme vantaggio che ti offre l'uso di variabili private (e, più in generale, dell'incapsulamento ).

Inoltre, non è proprio una "crisi di fiducia". Se rendi pubblico un dato, non puoi assicurarti che nessuno dipenda da esso. Spesso è molto conveniente dipendere da alcune variabili specifiche dell'implementazione, invece di passare attraverso l'interfaccia pubblica, specialmente nel calore di una scadenza. Inoltre, gli sviluppatori non si renderanno conto che dipendono da qualcosa che potrebbe cambiare.

Quindi questo tipo di risposte alle tue altre domande, spero. Tutti i dettagli dell'implementazione devono essere privati ​​e la parte pubblica deve essere un'interfaccia piccola, concisa e ben definita per l'utilizzo della classe.


24
IMO riguarda anche la comunicazione tra l'autore lib e il consumatore lib. L'interfaccia pubblica è come "usa questo" e i privati ​​sono come "non usarlo" tranne quello in Java, non puoi davvero usarlo per caso se lo rendi privato, quindi è più sicuro e più chiaro in quel modo.
Chakrit,

5
@chakrit e altri: tieni presente che coloro che sono davvero disponibili a utilizzare i tuoi campi e metodi privati possono farlo (tramite la riflessione). privateè inferiore a "non destinato principalmente alla sicurezza", non fornisce alcuna "sicurezza" di cui parlare. È solo un suggerimento forte (fornito tramite il compilatore) di non accedervi.

@delnan nota la frase "per caso" sì forse dovrei essere più chiaro su questo.
Chakrit,

@chakrit Sì, non intendevo implicare che tu avessi torto. Volevo solo promuovere questo punto.

1
@delnan: i campi privati ​​forniscono, in alcune lingue, determinate forme di sicurezza. Ad esempio, vedere la risposta di Eric Lippert a Livelli di accesso e modificatori (privati, sigillati, ecc.) Servono a scopi di sicurezza in C #? .
Brian,

25

La parola chiave qui è incapsulamento . In OOP si desidera utilizzare le variabili private per applicare l'incapsulamento corretto dei propri oggetti / classi.

Mentre altri programmatori non sono pronti a prenderti, interagiscono con il tuo codice. Se non rendi privata una variabile, potrebbe far riferimento ad essa nel proprio codice senza voler fare alcun danno. Tuttavia, se devi tornare alla tua classe e cambiare qualcosa, non sai più chi usa quale variabile e dove. L'obiettivo dell'incapsulamento è rendere esplicita l'interfaccia esterna della classe in modo da sapere che solo questi (in genere) metodi potrebbero essere stati utilizzati da altri.

  1. Pertanto, le variabili private assicurano che la variabile corrispondente rimanga solo nella classe di definizione. Se è necessario modificarlo, la modifica è locale alla classe stessa.

  2. Nei linguaggi tradizionali come C ++ o Java, di solito rendi tutto privato e accessibile solo dai corrispondenti getter e setter. Non c'è bisogno di decidere molto davvero.

  3. A volte, f.ex. in una struttura C ++, è necessaria una classe solo per raggruppare diverse cose. Ad esempio, considera una classe Vector che ha solo un xe un yattributo. In questi casi, puoi consentire l'accesso diretto a questi attributi dichiarandoli pubblici. In particolare, non devi preoccuparti se qualche codice esterno modifica un oggetto della tua classe scrivendo direttamente nuovi valori in xo y.

Come ulteriore punto, si noti che la questione è considerata leggermente diversa in altre lingue. Ad esempio, i linguaggi fortemente radicati nella programmazione funzionale enfatizzano l'immutabilità dei dati, ovvero i valori dei dati non possono essere modificati affatto. In questi casi, non devi preoccuparti di ciò che altri programmatori (o meglio il loro codice) fanno ai tuoi dati. Semplicemente non possono fare nulla che possa influire sul codice, poiché tutti i dati sono immutabili.

In quelle lingue, ottieni quindi qualcosa chiamato principio di accesso uniforme , in cui uno deliberatamente non distingue metodi come getter e setter, ma fornisce l'accesso diretto alla variabile / funzione. Quindi potresti dire che le dichiarazioni private sono molto più popolari negli scenari orientati agli oggetti.

Ciò mostra anche come l'ampliamento delle tue conoscenze per includere altri campi ti consente di visualizzare i concetti esistenti in un modo completamente nuovo.


1
+1 "Mentre gli altri programmatori non sono in cerca di te, interagiscono con il tuo codice." I programmatori che usano il tuo codice non sono intrinsecamente malvagi. Usando le variabili private ti assicuri che loro (e tu, in futuro) non ti facciano male usando il codice. Ti aiuta anche a progettare un'API migliore e documentarla.
szalski,

7

Le variabili private assicurano che i riferimenti successivi al di fuori dell'ambito di un oggetto o di una funzione non influenzino inavvertitamente altre variabili. Per i grandi progetti di programmazione, questo può aiutare a evitare molti problemi interessanti (che di solito non vengono colti dal compilatore).

Ad esempio, linguaggi prototipici come Javascript possono consentire agli utenti di intonare le variabili come ritengono opportuno:

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

Se quella variabile fosse privata, non sarebbe possibile cambiarla dall'esterno:

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

Detto questo, non tutte le variabili devono essere private e l'uso eccessivo di variabili private può effettivamente rendere il codice più ingombrante. Campi triviali che non incidono seriamente su un oggetto non sono necessari get()e set()metodi.

Le variabili private rendono anche più semplice espandere il codice in futuro, senza fare affidamento su una documentazione pesante su ciò che fanno le numerose variabili pubbliche. Vi è una minore minaccia di interruzione accidentale della funzionalità se è possibile sovrascrivere meno variabili.

Le variabili pubbliche dovrebbero essere utilizzate quando un oggetto / funzione accederà ad altri oggetti / funzioni, poiché di norma le variabili private non possono farlo. Potresti avere da poche a un bel po 'di variabili pubbliche, e non è male usarle se sono usate correttamente.


Non è ovvio perché avvisare 3 sarebbe un "uh oh!" in questo caso. Forse è quello che il programmatore voleva che accadesse.
immibis

@immibis Forse, e forse avrei dovuto approfondire di più la risposta. Ma l'accesso alle proprietà può aprire la porta alla violazione di alcuni principi OOP come il principio aperto-chiuso o LoD, poiché potenzialmente stai esponendo i dettagli dell'implementazione. 'ovviamente al tuo punto dipende da quale sia esattamente la proprietà. La maggior parte delle lingue usa gli oggetti come riferimenti e quando i riferimenti degli oggetti vengono fatti passare e gli altri sviluppatori cambiano silenziosamente le proprietà, può essere DAVVERO difficile eseguire il debug. IMO è molto più semplice ed estendibile lavorare con i metodi se si dispone di un'istanza di classe.
Jeffrey Sweeney,

7

Ci sono alcune buone risposte che citano i benefici per i futuri manutentori e utenti di una classe. Tuttavia, ci sono anche vantaggi per il design originale. Fornisce un chiaro punto di demarcazione tra quando il tuo obiettivo è rendere le cose più facili per te stesso e quando il tuo obiettivo è rendere le cose più facili per l'utente della classe. Quando scegli tra pubblico e privato, segnali al tuo cervello di passare a una modalità o all'altra e ti ritrovi con un'API migliore.

Non è che le lingue senza privacy rendono impossibile tale progettazione, solo meno probabile. Invece di essere spinto a scrivere qualcosa del genere foo.getBar(), le persone sono inclini a pensare che un getter non sia necessario, perché è più facile da scrivere foo.bar, ma poi quella decisione non viene rivisitata quando in seguito si finisce con mostruosità più lunghe come obj.container[baz].foo.bar. I programmatori che non hanno mai lavorato in un linguaggio più rigoroso potrebbero anche non vedere cosa c'è che non va.

Ecco perché nelle lingue senza privacy le persone spesso adottano standard di denominazione che lo simulano, come anteporre un carattere di sottolineatura a tutti i membri "privati". È un segnale utile anche quando la lingua non lo impone.


3

Tutte le variabili dovrebbero essere private a meno che non debbano assolutamente essere pubbliche (il che non è quasi mai, dovresti usare proprietà / getter e setter).

Le variabili forniscono in gran parte lo stato dell'oggetto e le variabili private impediscono ad altri di entrare e cambiare lo stato dell'oggetto.


5
Una visione troppo ristretta dell'argomento. Ci sono casi in cui l'accesso al campo pubblico è garantito, anche preferito
Roland Tepp l'

Si possono certamente progettare oggetti il ​​cui stato non può essere modificato (oggetti immutabili), ma questa non è una regola generale applicata a tutte le classi. Nella mia esperienza, la maggior parte degli oggetti rende molto facile per gli altri cambiare lo stato dell'oggetto.
David K,

1
@DavidK Forse ciò che bbb intendeva dire è che "le variabili private impediscono agli altri di entrare e cambiare indiscriminatamente lo stato dell'oggetto". I metodi pubblici possono modificare lo stato privato dell'oggetto, ma solo nei modi necessari e coerenti per il funzionamento dell'oggetto.
Max Nanasy,

@ Max Nanasy: Sì, si può controllare come viene modificato lo stato quando si offrono solo metodi nell'interfaccia pubblica. Ad esempio, potrebbe esserci una relazione tra i membri che deve essere soddisfatta affinché l'oggetto sia "autoconsistente" e si potrebbe consentire che uno stato autoconsistente sia cambiato solo in un altro stato autoconsistente. Se tutte queste variabili sono pubbliche, non è possibile applicarle. Ma possono esserci anche oggetti in cui non si desidera consentire alcun cambiamento, quindi è importante chiarire di quali di queste cose stiamo parlando.
David K,

2
  • Cosa impediscono le variabili private?

Si tratta di chiarire quali proprietà e metodi sono interfaccia e quali sono in realtà funzionalità di base. I metodi / proprietà pubblici riguardano altri codici spesso altri codici degli sviluppatori che utilizzano i tuoi oggetti. Non ho mai lavorato su team di 100+ nello stesso progetto, ma nella mia esperienza di forse team di 3-5 con un massimo di altri 20 sviluppatori che usano cose che ho scritto, le altre preoccupazioni sembrano sciocche.

Nota: sono principalmente uno sviluppatore JavaScript. In genere non mi preoccupo che altri sviluppatori visualizzino il mio codice e opero nella piena consapevolezza che potrebbero semplicemente ridefinire le mie cose in qualsiasi momento. Presumo che siano abbastanza competenti da sapere prima cosa stanno facendo. In caso contrario, è improbabile che lavorerei in un team che non utilizza il controllo del codice sorgente.

  • Come decidi se un determinato insieme di proprietà deve essere privato o no? Se per impostazione predefinita ogni campo DOVREBBE essere privato, allora perché ci sono membri di dati pubblici in una classe?

Pensavo fosse sciocco mettere getter e setter su proprietà private quando non si eseguiva realmente alcun tipo di validazione o altro trattamento speciale della proprietà da impostare. Continuo a non pensare che sia sempre necessario, ma quando hai a che fare con grandi dimensioni, elevata complessità, ma soprattutto molti altri sviluppatori che fanno affidamento sul comportamento dei tuoi oggetti in modo coerente, può essere utile fare le cose in modo modo coerente e uniforme. Quando le persone vedono i metodi chiamati getThatesetThat, sanno esattamente quali sono le intenzioni e possono scrivere i loro oggetti per interagire con i tuoi con l'aspettativa che otterranno sempre pomodori anziché tomahtos. In caso contrario, sanno che il tuo oggetto sta dando loro qualcosa che probabilmente non dovrebbe, il che significa che sta permettendo a qualche altro oggetto di fare qualcosa con quei dati che probabilmente non dovrebbe. Puoi controllarlo quando se ne presenta la necessità.

L'altro grande vantaggio è che è più facile avere i tuoi oggetti a disposizione o interpretare i valori in modo diverso da un getter o setter in base a un qualche tipo di contesto di stato variabile. Poiché stanno accedendo alle tue cose con un metodo, è molto più facile cambiare il modo in cui il tuo oggetto funziona in seguito senza rompere altro codice che dipende da esso. Il principio importante è che solo il tuo oggetto cambia effettivamente i dati per i quali lo hai reso responsabile. Ciò è particolarmente importante per mantenere il tuo codice liberamente accoppiato, il che è una grande vittoria in termini di portabilità e facilità di modifica.

  • In quali circostanze una variabile dovrebbe essere resa pubblica?

Con le funzioni di prima classe (puoi passare le funzioni come argomenti), non riesco a pensare a molte grandi ragioni oltre a non essere estremamente necessario per farlo su progetti su scala ridotta. Senza di esso, suppongo che potresti avere membri che vengono elaborati pesantemente e regolarmente da altri oggetti nella misura in cui sembra un po 'crudele chiamare costantemente get e impostare su un oggetto che non tocca realmente quei dati, ma che in stesso mi farebbe chiedermi perché l'oggetto fosse responsabile di quei dati. In generale, vorrei tendere a riesaminare la mia architettura per individuare eventuali difetti prima di decidere se è necessaria una proprietà di dati pubblici. IMO, non c'è niente di sbagliato in una lingua che ti consente di fare qualcosa che di solito è una cattiva idea. Alcune lingue non sono d'accordo.


IMHO, non c'è nulla di particolarmente sbagliato nell'avere una classe pubblica il cui unico scopo è quello di esporre le variabili pubbliche. In effetti, la JVM ha un certo numero di classi incorporate a tale scopo: int[], double[], Object[], ecc Uno dovrebbe, tuttavia, essere molto attenti a come ci si espone le istanze di tale classe. Il significato di void CopyLocationTo(Point p);[accettare a Pointdal chiamante] è più chiaro di Point location(), poiché non è chiaro quale effetto Point pt = foo.location(); pt.x ++;avrà sulla posizione di foo.
supercat il

2

Vedi questo mio post per una domanda correlata su SO .

In sostanza, l'ambito variabile ti consente di mostrare ai consumatori del tuo codice ciò che dovrebbero e non dovrebbero fare confusione. Una variabile privata può contenere dati che sono stati "controllati" utilizzando un setter proprietà o un metodo di elaborazione per garantire che l'intero oggetto sia in stato coerente. La modifica diretta del valore della variabile privata può rendere incoerente l'oggetto. Rendendolo privato, qualcuno deve lavorare sodo e disporre di autorizzazioni di runtime davvero elevate per poterlo modificare.

L'ambito del membro corretto è quindi la chiave nel codice di auto-documentazione.


2

Parlerò del valore dell'incapsulamento da una prospettiva diversa usando un esempio reale. Qualche tempo fa (primi anni '80) è stato scritto un gioco per il Radio Shack Color Computer chiamato Dungeons of Daggorath. Alcuni anni fa, Richard Hunerlach lo portò da un elenco di assemblatori di carta su C / C ++ ( http://mspencer.net/daggorath/dodpcp.html ). Qualche tempo dopo, ho ottenuto il codice e ho iniziato a ricodificarlo per fornire un migliore incapsulamento ( http://dbp-consulting.com/stuff/ ).

Il codice era già stato inserito in diversi oggetti per gestire la programmazione, il video, l'input dell'utente, la creazione di dungeon, mostri, ecc. Ma si poteva sicuramente dire che era stato portato da assemblatore. Il mio compito più grande era aumentare l'incapsulamento. Con ciò intendo ottenere diverse parti del codice per ottenere il naso dagli affari degli altri. Ad esempio, c'erano molti posti che avrebbero cambiato direttamente le variabili video per avere qualche effetto. Alcuni lo hanno fatto con il controllo degli errori, altri no, alcuni avevano idee leggermente diverse su cosa significasse cambiare quella cosa. C'era molta duplicazione del codice. Invece, la sezione video doveva avere un'interfaccia per eseguire le attività desiderate e il codice per farlo poteva essere tutto in un posto, un'idea, un posto per il debug. Questo genere di cose dilagava.

Mentre il codice iniziava a essere preso in giro, i bug che non erano stati nemmeno diagnosticati scomparvero. Il codice è diventato di qualità superiore. Ogni attività è diventata la responsabilità di un posto nel codice e c'era solo un posto per farlo bene. (Trovo ancora di più ogni volta che faccio un altro passaggio attraverso il codice.)

Tutto ciò che è visibile sul tuo codice è la tua interfaccia. Che tu lo voglia dire o no. Se limiti la visibilità il più possibile, non sarai tentato di mettere il codice nel posto sbagliato in seguito. Rende evidente quale parte del codice è responsabile di quali dati. Rende il design migliore, più pulito, più semplice, più elegante.

Se si rende un oggetto responsabile dei propri dati e si forniscono interfacce a tutti gli altri che hanno bisogno di qualcosa, il codice diventa MOLTO più semplice. Cade e basta. Hai piccole routine semplici che fanno solo una cosa. Meno complessità == meno bug.


Il duro equilibrio tra "la libertà dei nostri utenti lib" e "meno problemi per noi". Sto iniziando a credere che l'incapsulamento sia migliore, nel senso che prevarrò i bug sulla mia codifica e aiuterò anche gli utenti finali a prevenire i bug. Ma la mancanza di libertà può anche semplicemente metterli da parte, alla ricerca di alternative ... Può essere la codifica non ancora utilizzata ma funzionalità previste attraverso metodi pubblici possono aiutare a bilanciare ciò, ma richiede più tempo.
Aquarius Power il

Peccato che la versione refactored non sia su github ....
jmoreno,

2

Non ha nulla a che fare con la fiducia o la paura degli attacchi, riguarda esclusivamente l'incapsulamento, non forzare informazioni non necessarie sull'utente della classe.

Considera le costanti private: non devono contenere valori segreti (devono essere archiviati altrove), non possono essere modificati, non devono essere passati nella tua classe (altrimenti dovrebbero essere pubblici). L'unico uso possibile per loro è come costanti nelle ALTRE classi. Ma se lo fai, quelle classi ora dipendono dalla tua classe, per fare un lavoro che non è correlato alla tua classe. Se si modifica la costante, altre classi potrebbero interrompersi. È negativo per entrambe le parti: come scrittore della tua classe, vuoi che la libertà cambi il più possibile e non devi preoccuparti di cose al di fuori del tuo controllo. Un consumatore della tua classe vuole poter dipendere dai dettagli esposti della tua classe, senza preoccuparti che tu la modifichi e rompa il loro codice.

Un consumatore della tua classe vuole sapere tutto ciò che è necessario per interagire con la tua classe e non vuole sapere nulla della tua classe che non cambi il modo in cui lo fanno: è inutile banalità. Se hai usato una lingua con la riflessione, quanto spesso l'hai usata per imparare non come una classe fa qualcosa o dove sta generando un'eccezione inaspettatamente, ma semplicemente il nome dei campi e dei metodi privati? Non scommetto mai. Perché non hai alcuna utilità per quella conoscenza.


1

Il concetto OOP ha ereditarietà ha una delle sue caratteristiche (Java o C ++). Quindi se ereditiamo (nel senso che accediamo alle variabili della classe ereditata), c'è la possibilità di influenzare quelle variabili. Quindi dobbiamo decidere se le variabili possono essere modificate o meno.

Solo a questo scopo, stiamo utilizzando modificatori di accesso in OOP. Uno dei modificatori è privato, il che significa che è possibile accedervi solo da quella classe. Qualsiasi altra classe non può influenzare quelle variabili.

Come sappiamo, protetto significa che è possibile accedervi dalla classe che erediterà.

Perché esiste un concetto modificatore in OOP, è per questi motivi (qualsiasi classe può accedere ad altre variabili di classe usando il concetto OOP). Se non esiste un concetto di modificatore, significa che sarebbe stato difficile ereditare le classi o utilizzare altri concetti OOP.


1

Come affermato da altri, le variabili private sono utili per evitare errori di utilizzo che portano l'oggetto in uno stato incoerente e difficile da rintracciare bug ed eccezioni impreviste.

D'altra parte, ciò che è stato per lo più ignorato dagli altri riguarda i campi protetti.

Una sottoclasse estesa avrà pieno accesso ai campi protetti, rendendo l'oggetto fragile come se tali campi fossero pubblici, ma tale fragilità è limitata alla classe estendibile (a meno che non esponga ulteriormente tali campi).

Quindi, i campi pubblici sono difficili da considerare buoni e fino ad oggi l'unico motivo per usarli è per le classi usate come parametro di configurazione (una classe molto semplice con molti campi e senza logica, quindi quella classe viene passata come parametro da sola a qualche metodo).

D'altra parte, i campi privati ​​riducono la flessibilità del codice ad altri utenti.

Flessibilità vs problemi, pro e contro:

Gli oggetti istanziati dal tuo codice nella classe vanilla con campi protetti sono sicuri e sono di tua esclusiva responsabilità.

D'altra parte, gli oggetti che estendono la tua classe con campi protetti, istanziati dagli utenti del tuo codice, sono la loro responsabilità, non la tua.

Quindi, campi / metodi protetti non ben documentati, o se gli utenti non capiscono davvero come utilizzare tali campi e metodi, hanno buone probabilità di causare problemi inutili a se stessi e a te.

D'altra parte, rendere la maggior parte delle cose private ridurrà la flessibilità degli utenti e potrebbe persino metterli via alla ricerca di alternative mantenute, poiché potrebbero non voler creare e mantenere un fork solo per fare in modo che le cose accadano a modo loro.

Quindi, un buon equilibrio tra privato, protetto e pubblico è ciò che conta davvero.

Ora, decidere tra privato e protetto è il vero problema.

Quando utilizzare protetto?

Ogni volta che capisci che un campo può essere altamente flessibile, dovrebbe essere codificato come protetto. Quella flessibilità è: dal diventare null (dove null è sempre verificato e riconosciuto come uno stato valido senza generare eccezioni), ad avere vincoli prima di essere usato dalla tua classe ex. > = 0, <100 ecc. E riparato automaticamente per i valori di over / under-flow, generando al massimo un messaggio di avviso.

Quindi, per un tale campo protetto potresti creare un getter e usarlo solo (invece di usare direttamente la variabile di campo), mentre altri utenti potrebbero non usarlo, nel caso in cui desiderino una maggiore flessibilità per il loro codice specifico, nel mio esempio potrebbe essere come : se vogliono che i valori negativi funzionino correttamente nella loro classe estesa.


-1

imo @tdammers non ha ragione e in realtà è fuorviante.

Esistono variabili private per nascondere i dettagli di implementazione. La tua classe Apotrebbe utilizzare un arrayper memorizzare i punteggi. Domani potresti voler usare un treeo priority queueinvece. Tutti gli utenti della tua classe hanno bisogno di un modo per inserire punteggi e nomi addScore()e un modo per capire chi sono i primi 10 getTop(n).

Non devono accedere alla struttura dei dati sottostante. Suona alla grande? Bene, ci sono alcuni avvertimenti.

Non dovresti comunque conservare molto stato, la maggior parte non è necessaria. La memorizzazione dello stato complicherà il codice anche quando è "segregato" in una classe specifica. Pensaci, quella variabile privata probabilmente è cambiata perché un altro oggetto ha chiamato un metodo di quella classe. Devi ancora capire quando e dove è stato chiamato quel metodo e quel metodo pubblico può essere chiamato ovunque teoricamente.

La cosa migliore che puoi fare è limitare la quantità di stato che il tuo programma contiene e usare funzioni pure quando possibile.


-1
  • Accedere a una variabile significa accedere al suo valore durante l'esecuzione del programma, rendendo una variabile privata protegge il suo valore durante l'esecuzione del codice.
  • Il punto del cosiddetto "nascondimento dei dati" è quello di mantenere i dati interni nascosti da altre classi che usano la classe. Le altre classi dovrebbero accedere al comportamento solo chiamando metodi sulla classe, non modificando direttamente i valori delle variabili.
  • Rendendo la variabile un membro di dati privato, è possibile assicurarsi più facilmente che il valore non venga mai modificato o modificato. D'altra parte, se la variabile è pubblica, un'altra classe potrebbe modificare o cambiare il valore che può causare l'arresto anomalo di altre parti del codice.

1
questo non sembra offrire nulla di sostanziale rispetto ai punti formulati e spiegati nelle precedenti risposte del 17
moscerino

-4

Dovresti prima capire il concetto di programmazione orientata agli oggetti. Ha astrazione, incapsulamento ecc.

Astrazione: ottieni l'idea della logica senza bisogno di conoscere i dettagli sottolineati dell'implementazione.

Incapsulamento: non è possibile visualizzare l'implementazione sottolineata dell'oggetto. Solo tu puoi vedere l'interfaccia pubblica dell'oggetto.

Ora in un'implementazione specifica con uno dei programmi orientati agli oggetti come C #, Java, C ++ è possibile implementare questi concetti.

privato - L'implementazione che dovrebbe essere nascosta al mondo esterno. In modo che tu possa cambiarlo e l'utente della tua classe non sia interessato.

pubblica - Questa è l'interfaccia tramite la quale puoi usare il tuo oggetto.


1
protetto - accessibile direttamente da sottoclassi (estensori) (java).
Aquarius Power il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.