Perché i campi privati non sono abbastanza protetti?

262

La visibilità private dei campi di classe / proprietà / attributi è utile? In OOP, prima o poi, creerai una sottoclasse di una classe e in tal caso, è bene comprendere e poter modificare completamente l'implementazione.

Una delle prime cose che faccio quando sottoclassi una classe è di cambiare un gruppo di metodi private in protected . Tuttavia, nascondere i dettagli dal mondo esterno è importante, quindi abbiamo bisogno di protected e non solo public .

La mia domanda è: conosci un caso d'uso importante in cui private invece di protected è un buon strumento, o due opzioni " protected & public " sono sufficienti per i linguaggi OOP?

    
posta Adam Libuša 11.03.2016 - 10:17
fonte

17 risposte

224

Perché come dici tu, protected ti lascia ancora con la possibilità di "modificare completamente l'implementazione". Non protegge veramente nulla all'interno della classe.

Perché ci preoccupiamo di "proteggere genuinamente" le cose all'interno della classe? Perché altrimenti sarebbe impossibile modificare i dettagli di implementazione senza rompere il codice client . In altre parole, le persone che scrivono sottoclassi sono anche "il mondo esterno" per la persona che ha scritto la classe base originale.

In pratica, i membri di protected sono essenzialmente una "classe API pubblica per sottoclassi" e devono rimanere stabili e retrocompatibili tanto quanto public membri. Se non avessimo la possibilità di creare veri membri di private , allora niente in un'implementazione sarebbe mai sicuro di cambiare, perché non sareste in grado di escludere la possibilità che (non- malizioso) il codice client è in qualche modo riuscito a dipendere da esso.

Per inciso, mentre "In OOP, prima o poi, stai per creare una sottoclasse di una classe" è tecnicamente vero, la tua argomentazione sembra fare l'assunzione molto più strong che "prima o poi, hai intenzione di fare una sottoclasse di ogni classe "che quasi certamente non è il caso.

    
risposta data 11.03.2016 - 10:30
fonte
255

In OOP, sooner or later, you are going to make a subclass of a class

Questo è sbagliato. Non tutte le classi sono destinate alla sottoclasse e alcuni linguaggi OOP staticamente digitati hanno anche caratteristiche per prevenirlo, ad esempio final (Java e C ++) o sealed (C #).

it is good to understand and being able to modify the implementation completely.

No, non lo è. È un bene per una classe essere in grado di definire chiaramente la sua interfaccia pubblica e preservare i suoi invarianti anche se è ereditata da.

In generale, il controllo degli accessi riguarda la compartimentazione. Vuoi che una singola parte del codice sia compresa senza dover capire in dettaglio come interagisce con il resto del codice. L'accesso privato lo consente. Se tutto è almeno protetto, devi capire cosa fa ogni sottoclasse per capire come funziona la classe base.

O per dirla nei termini di Scott Meyers: le parti private di una classe sono influenzate da una quantità limitata di codice: il codice della classe stessa.

Le parti pubbliche sono potenzialmente interessate da ogni bit di codice esistente e da ogni bit di codice ancora da scrivere, che è una quantità infinita di codice.

Le parti protette sono potenzialmente interessate da ogni sottoclasse esistente e da ogni sottoclasse ancora da scrivere, che è anche una quantità infinita di codice.

La conclusione è che protetta ti dà molto poco più del pubblico, mentre privato ti dà un reale miglioramento. È l'esistenza dello specificatore di accesso protetto che è discutibile, non privato.

    
risposta data 11.03.2016 - 10:34
fonte
33

Sì, i campi privati sono assolutamente necessari. Proprio questa settimana ho avuto bisogno di scrivere un'implementazione personalizzata del dizionario in cui ho controllato ciò che è stato inserito nel dizionario. Se il campo del dizionario dovesse essere reso protetto o pubblico, allora i controlli che avrei scritto con tanta attenzione avrebbero potuto essere facilmente aggirati.

I campi privati in genere forniscono protezione che i dati sono come previsto dal codificatore originale. Rendi tutto protetto / pubblico e guida un allenatore e cavalli attraverso tali procedure e convalida.

    
risposta data 11.03.2016 - 10:44
fonte
12

Quando tenti di ragionare formalmente sulla correttezza di un programma orientato agli oggetti è typical per utilizzare un approccio modulare che coinvolge invarianti oggetto . In questo approccio

  1. I metodi hanno associato con loro pre e post condizioni (contratti).
  2. Gli oggetti sono associati con invarianti.

Il ragionamento modulare su un oggetto procede come segue (ad un primo approssimativo almeno)

  1. Dimostra che il costruttore dell'oggetto stabilisce l'invariante
  2. Per ogni metodo non privato, si supponga che l'invarianza di oggetto e la precondizione del metodo tengano premuto sulla voce, quindi si provi che il corpo del codice implica che la postcondizione e l'invariante rimangono sul metodo exit

Immagina di verificare object A usando l'approccio sopra. E ora desideri verificare method g di object B che chiama method f di object A . Il ragionamento modulare ci consente di ragionare su method g senza dover riconsiderare l'implementazione di method f . Se possiamo stabilire l'invariante di object A e la precondizione di method f nel sito di chiamata in method g, , possiamo prendere la condizione post di method f come riepilogo del comportamento della chiamata al metodo. Inoltre sapremo anche che dopo la chiamata ritorna ancora l'invariante di A .

Questa modularità del ragionamento è ciò che ci permette di pensare formalmente a grandi programmi. Possiamo ragionare su ciascuno dei metodi individualmente e quindi comporre i risultati di questo ragionamento a sua volta per ragionare su parti più ampie del programma.

I campi privati sono molto utili in questo processo. Per sapere che l'invariante di un oggetto continua a rimanere tra due chiamate di metodo su quell'oggetto, normalmente ci basiamo sul fatto che l'oggetto non viene modificato nel periodo intermedio.

Affinché il ragionamento modulare funzioni in un contesto in cui gli oggetti non hanno campi privati, dovremmo avere un modo per garantire che qualunque cosa un campo sia stato impostato da un altro oggetto, che l'invariante sia sempre ristabilito ( dopo il campo impostato). È difficile immaginare un invariante di oggetti che non ha importanza indipendentemente dal valore dei campi dell'oggetto, ed è anche utile per ragionare sulla correttezza del programma. Probabilmente dovremmo inventare alcune complicate convenzioni sull'accesso al campo. E probabilmente anche perderà alcuni (al limite anche tutti) la nostra capacità di ragionare in modo modulare.

Campi protetti

I campi protetti ripristinano alcune delle nostre capacità di ragionare in modo modulare. A seconda della lingua, protected può limitare la possibilità di impostare un campo per tutte le sottoclassi o tutte le sottoclassi e le classi dello stesso pacchetto. Spesso accade che non abbiamo accesso a tutte le sottoclassi quando ragioniamo sulla correttezza di un oggetto che stiamo scrivendo. Ad esempio, potresti scrivere un componente o una libreria che verranno in seguito utilizzati in un programma più grande (o in più programmi più grandi), alcuni dei quali potrebbero non essere stati ancora scritti. In genere non si sa se e in quali modi può essere sottoclassato.

Tuttavia, di solito è incombente su una sottoclasse mantenere l'invariante dell'oggetto della classe che estende. Quindi, in una lingua in cui proteggere significa solo "sottoclasse" e dove siamo disciplinati per garantire che le sottoclassi mantengano sempre gli invarianti della loro superclasse, si potrebbe sostenere che la scelta di utilizzare protetti anziché privati perde solo una modularità minima .

Anche se ho parlato di ragionamento formale, è pensato spesso che quando i programmatori informano la ragione la correttezza del loro codice a volte si basano anche su tipi di argomenti simili.

    
risposta data 11.03.2016 - 14:04
fonte
8

private variabili in una classe sono migliori di protected per lo stesso motivo per cui un'istruzione break all'interno di un blocco switch è migliore di un'istruzione goto label ; che è che i programmatori umani sono soggetti a errori.

Le variabili

protected si prestano a un abuso non intenzionale (errori del programmatore), proprio come l'istruzione goto si presta alla creazione del codice spaghetti.

È possibile scrivere codice funzionante senza errori utilizzando protected variabili di classe? Sì, naturalmente! Così come è possibile scrivere codice funzionante senza errori usando goto ; ma come dice il cliché "Solo perché puoi, non significa che dovresti!"

Classi, e in effetti il paradigma OO, esistono per difendersi dagli sfortunati programmatori umani incline agli errori che commettono errori. La difesa contro gli errori umani è valida solo come le misure difensive incorporate nella classe. Rendere l'implementazione della tua classe protected equivale a far saltare un'enorme buca nei muri di una strongzza.

Le classi base non hanno alcuna conoscenza delle classi derivate. Per quanto riguarda una classe base, protected in realtà non ti dà più protezione di public , perché non c'è nulla che impedisca a una classe derivata di creare un% gid / setter public che si comporta come una backdoor.

Se una classe base consente un accesso non impedito ai dettagli di implementazione interna, diventa impossibile per la classe stessa difendersi dagli errori. Le classi base non hanno assolutamente alcuna conoscenza delle loro classi derivate e quindi non hanno modo di proteggersi dagli errori commessi in quelle classi derivate.

La cosa migliore che una classe base può fare è nascondere la maggior parte della sua implementazione possibile come private e mettere abbastanza restrizioni per evitare rotture di cambiamenti da classi derivate o da qualsiasi altra cosa al di fuori della classe.

In definitiva, esistono linguaggi di alto livello per ridurre al minimo gli errori umani. Esistono anche buone pratiche di programmazione (come i principi SOLID ) per ridurre al minimo gli errori umani.

Gli sviluppatori di software che ignorano le buone pratiche di programmazione hanno una probabilità molto più elevata di errori e sono più propensi a produrre soluzioni irrinunciabili non funzionanti. Coloro che seguono le buone pratiche hanno una probabilità molto più bassa di fallimento e sono più propensi a produrre soluzioni manutenibili funzionanti.

    
risposta data 11.03.2016 - 11:06
fonte
4

Le classi ereditabili hanno due contratti, uno con titolari di riferimenti a oggetti e con classi derivate. I membri pubblici sono vincolati dal contratto con i titolari di riferimento e i membri protetti sono vincolati dal contratto con le classi derivate.

Rendere membri protected lo rende una classe base più versatile, ma spesso limiterà il modo in cui le future versioni della classe potrebbero cambiare. Rendere membri private consente all'autore della classe più versatilità di cambiare il funzionamento interno della classe, ma limita i tipi di classi che possono essere utilmente derivati da esso.

Ad esempio, List<T> in .NET rende privato il backing store; se fosse protetto, i tipi derivati potrebbero fare alcune cose utili che altrimenti non sarebbero possibili, ma le versioni future di List<T> avrebbero dovuto sempre usare il suo grintoso backing monolitico anche per liste contenenti milioni di elementi. Rendere privato il backing store consentirebbe alle versioni future di List<T> di utilizzare un backing store più efficiente senza interrompere le classi derivate.

    
risposta data 11.03.2016 - 22:33
fonte
4

Penso che nella tua argomentazione vi sia un assunto chiave che quando qualcuno scrive una classe non sa chi potrebbe estendere quella classe lungo la strada e per quale motivo . Dato questo presupposto, la tua argomentazione avrebbe perfettamente senso perché ogni variabile che rendi privata potrebbe potenzialmente tagliare via qualche via di sviluppo lungo la strada. Tuttavia, respingerei tale ipotesi.

Se tale ipotesi viene rifiutata, ci sono solo due casi da considerare.

  1. L'autore della classe originale aveva idee molto chiare sul motivo per cui potrebbe essere esteso (ad esempio è un BaseFoo e ci saranno diverse implementazioni concrete di Foo in fondo alla strada).

In questo caso, l'autore sa che qualcuno estenderà la classe e perché e quindi saprà esattamente cosa rendere protetto e cosa rendere privato. Stanno usando la distinzione privata / protetta per comunicare un'interfaccia di ordinamento all'utente che crea la sottoclasse.

  1. L'autore della classe figlia sta tentando di modificare un comportamento in una classe genitore.

Questo caso dovrebbe essere raro (potresti sostenere che non è legittimo) e non è preferibile semplicemente modificare la classe originale nel codice originale. Potrebbe anche essere un sintomo di cattivo design. In questi casi preferirei che l'hacking nel comportamento utilizzi solo altri hack come amici (C / C ++) e setAccessible(true) (Java).

Penso che sia sicuro respingere questa ipotesi.

Questo generalmente ricade sull'idea di composizione sull'ereditarietà . L'ereditarietà viene spesso insegnata come un modo ideale per ridurre il riutilizzo del codice, tuttavia raramente dovrebbe essere la prima scelta per il riutilizzo del codice. Non ho un semplice argomento di knock-down e può essere abbastanza difficile e controverso da capire. Tuttavia, nella mia esperienza con la modellazione di domini ho scoperto che utilizzo raramente l'ereditarietà senza avere una chiara comprensione di chi erediterà la mia classe e perché.

    
risposta data 11.03.2016 - 23:51
fonte
2

Tutti e tre i livelli di accesso hanno il loro caso d'uso, l'OOP sarebbe incompleto senza uno di essi. Di solito lo fai

  • imposta tutte le variabili / membri dati private . Non vuoi che qualcuno esterno faccia casino con i tuoi dati interni. Anche i metodi che forniscono funzionalità ausiliarie (pensate a calcoli basati su più variabili membro) all'interfaccia pubblica o protetta - sono solo per uso interno e potreste voler cambiare / miglioralo in futuro.
  • crea l'interfaccia generale della classe pubblica . Questo è ciò con cui gli utenti della tua classe originale dovrebbero lavorare, e come pensi che dovrebbero essere le classi derivate. Per fornire un incapsulamento corretto, di solito sono solo i metodi (e le classi helper / structs, enumerazioni, typedef, qualunque sia l'utente che deve lavorare con i tuoi metodi), non le variabili.
  • dichiara i metodi protetti che potrebbero essere utili per qualcuno che desidera estendere / specializzare la funzionalità della tua classe, ma non dovrebbe far parte dell'interfaccia pubblica - di fatto, di solito sollevi membri privati a protetti quando necessario. In caso di dubbio non lo fai, finché non lo sai
    1. la tua classe può / può / sarà sottoclasa,
    2. e avere una chiara idea di quali potrebbero essere i casi d'uso della sottoclasse.

E tu devii da questo schema generale solo se esiste un buon motivo ™ . Attenzione a "questo renderà la mia vita più facile quando posso accedere liberamente da fuori" (e all'esterno qui include anche sottoclassi). Quando implemento le gerarchie di classi, spesso inizio con classi che non hanno membri protetti, finché non arrivo a sottoclassi / estendendole / specializzandole, diventando le classi base di un framework / toolkit e talvolta spostando una parte della loro funzionalità originale a un livello superiore.

    
risposta data 12.03.2016 - 00:50
fonte
1

Una domanda più interessante, forse, è perché è necessario un altro tipo di campo rispetto al privato. Quando una sottoclasse deve interagire con i dati di una superclasse, così facendo crea direttamente un accoppiamento diretto tra i due, mentre l'utilizzo di metodi per fornire l'interazione tra i due consente un livello di riferimento indiretto che può consentire di apportare modifiche al superclasse che altrimenti sarebbe molto difficile.

Un certo numero di lingue (ad esempio Ruby e Smalltalk) non forniscono campi pubblici in modo che gli sviluppatori siano scoraggiati dall'accesso diretto alle loro implementazioni di classe, ma perché non andare oltre e avere solo campi privati? Non ci sarebbe alcuna perdita di generalità (perché la superclasse può sempre fornire accessori protetti per la sottoclasse), ma garantirebbe che le classi abbiano sempre almeno un piccolo grado di isolamento dalle loro sottoclassi. Perché questo non è un design più comune?

    
risposta data 12.03.2016 - 16:58
fonte
1

Un sacco di buone risposte qui, ma mi limiterò comunque a tirare i miei due centesimi. : -)

Private è buono per lo stesso motivo per cui i dati globali sono negativi.

Se una classe dichiara i dati come privati, allora si sa che l'unico codice che ha a che fare con questi dati è il codice della classe. Quando c'è un bug, non è necessario cercare in tutta la creazione per trovare ogni posto che potrebbe modificare questi dati. Sai che è in classe. Quando apporti una modifica al codice e cambi qualcosa sul modo in cui viene utilizzato questo campo, non devi rintracciare tutti i potenziali luoghi che potrebbero utilizzare questo campo e studiare se il tuo cambiamento pianificato li infrangerà. Sai che gli unici posti sono all'interno della classe.

Ho avuto molte, molte volte che ho dovuto apportare modifiche a classi che sono in una libreria e utilizzate da più app, e devo procedere con molta attenzione per assicurarmi di non rompere alcune app che conosco niente. Più dati pubblici e protetti ci sono, più possibilità di problemi.

    
risposta data 14.03.2016 - 05:29
fonte
1

Penso che valga la pena di menzionare alcune opinioni dissenzienti.

In teoria, è bene avere un livello di accesso controllato per tutti i motivi menzionati in altre risposte.

In pratica, troppo spesso durante la revisione del codice, vedo le persone (a cui piace usare il privato), che cambiano il livello di accesso da privato - > protetto e non troppo spesso da protetto - > pubblico. Quasi sempre, la modifica delle proprietà di classe comporta la modifica di setter / getter. Questi hanno sprecato gran parte del mio tempo (revisione del codice) e il loro (cambio del codice).

Mi infastidisce anche che ciò significa che le loro classi non sono chiuse per la modifica.

Questo era con il codice interno in cui puoi sempre modificarlo se ne hai bisogno. La situazione è peggiore con il codice di terze parti quando non è così facile cambiare il codice.

Quindi, quanti programmatori pensano che sia una seccatura? Bene, quanti usano i linguaggi di programmazione che non hanno privato? Ovviamente, le persone non usano solo quelle lingue perché non hanno specificatori privati, ma aiutano a semplificare le lingue e la semplicità è importante.

Imo è molto simile alla tipizzazione dinamica / statica. In teoria, la tipizzazione statica è molto buona. In pratica, impedisce solo il 2% di errori L'irragionevole efficacia della digitazione dinamica ... . L'utilizzo di private probabilmente previene l'errore meno di quello.

Penso che i principi SOLID siano buoni, vorrei che le persone si preoccupassero di loro più di quanto si preoccupino di creare una classe con pubblico, protetto e privato.

    
risposta data 14.03.2016 - 11:27
fonte
0

Vorrei anche aggiungere un altro esempio pratico del perché protected non è sufficiente. Nella mia università i primi anni intraprendono un progetto in cui devono sviluppare una versione desktop di un gioco da tavolo (che successivamente è stata sviluppata per un AI e collegata ad altri giocatori attraverso una rete). A loro viene fornito un codice parziale per avviarli, incluso un framework di test. Alcune delle proprietà della classe di gioco principale sono esposte come protected in modo che le classi di test che estendono questa classe abbiano accesso ad esse. Ma questi campi non sono informazioni sensibili.

Come TA per l'unità, spesso vedo gli studenti semplicemente facendo tutto il loro codice aggiunto protected o public (forse perché hanno visto l'altro protected e public roba e hanno presunto che dovrebbero seguire l'esempio). Chiedo loro perché il loro livello di protezione è inappropriato e molti non sanno perché. La risposta è che le informazioni sensibili che stanno esponendo alle sottoclassi significa che un altro giocatore può imbrogliare semplicemente estendendo quella classe e accedendo alle informazioni altamente sensibili per il gioco (essenzialmente la posizione nascosta degli avversari, immagino simile a come sarebbe se tu potrebbe vedere i pezzi dell'avversario su una nave da guerra estendendo qualche lezione). Ciò rende il loro codice molto pericoloso nel contesto del gioco.

Oltre a questo, ci sono molti altri motivi per mantenere qualcosa di privato anche per le sottoclassi. Potrebbe essere nascondere i dettagli di implementazione che potrebbero compromettere il corretto funzionamento della classe se modificati da qualcuno che non sa necessariamente cosa stanno facendo (principalmente pensando ad altre persone che usano il tuo codice qui).

    
risposta data 11.03.2016 - 23:55
fonte
0

I metodi / variabili privati saranno generalmente nascosti da una sottoclasse. Questa può essere una buona cosa.

Un metodo privato può fare supposizioni sui parametri e lasciare il controllo di integrità al chiamante.

Un metodo protetto dovrebbe input di controllo sanitario.

    
risposta data 13.03.2016 - 20:31
fonte
-1

"privato" significa: non inteso per essere modificato o accessibile da chiunque tranne la classe stessa. Non destinato a essere modificato o accessibile da sottoclassi. Sottoclassi? Quali sottoclassi? Non dovresti creare una sottoclasse di questo!

"protetto" significa: destinato a essere modificato o accessibile solo da classi o sottoclassi. Probabile deduzione che si suppone sottoclasse, altrimenti perché "protetto" e non "privato"?

C'è una chiara differenza qui. Se faccio qualcosa di privato, dovresti tenere le tue dita sporche fuori da esso. Anche se sei una sottoclasse.

    
risposta data 12.03.2016 - 13:08
fonte
-1

One of the first things I do when I subclass a class is to change a bunch of private methods to protected

Alcuni ragionamenti su private rispetto a protected metodi :

I metodi

private impediscono il riutilizzo del codice. Una sottoclasse non può utilizzare il codice nel metodo privato e potrebbe doverlo implementare di nuovo o implementare nuovamente i metodi che originariamente dipendono dal metodo privato & c;

D'altra parte, qualsiasi metodo che sia non private può essere visto come un'API fornita dalla classe a "il mondo esterno", nel senso che le sottoclassi di terze parti sono considerate "mondo esterno", come già suggerito da qualcun altro nella sua risposta.

È una cosa brutta? - Io non la penso così

Naturalmente, un'API (pseudo) pubblica blocca il programmatore originale e ostacola il refactoring di tali interfacce. Ma visto il contrario, perché un programmatore non dovrebbe progettare i propri "dettagli di implementazione" in un modo tanto pulito e stabile quanto la sua API pubblica? Dovrebbe usare private in modo che possa essere trascurato nel strutturare il suo codice "privato"? Pensando forse che potrebbe ripulirlo più tardi, perché nessuno se ne accorgerà? - No.

Il programmatore dovrebbe anche mettere un po 'di pensiero nel suo codice "privato", per strutturarlo in un modo che consenta o addirittura promuova il riutilizzo di quanto più possibile in primo luogo. Quindi le parti non private potrebbero non diventare tanto pesanti in futuro quanto alcuni temono.

Un sacco di codice (framework) che vedo adotta un uso incoerente di private : protected , metodi non definitivi che a malapena fanno qualcosa di più della delega a un metodo privato si trovano comunemente. protected , metodi non finalizzati il cui contratto può essere soddisfatto solo tramite l'accesso diretto ai campi privati.

Questi metodi non possono essere sovrascritti / migliorati logicamente, sebbene tecnicamente non ci sia nulla da fare per renderlo (compilatore) ovvio.

Vuoi estendere ed ereditare? Non rendere i tuoi metodi private .

Non vuoi alterare certi comportamenti della tua classe? Crea i tuoi metodi final .

Davvero non puoi avere il tuo metodo chiamato al di fuori di un certo contesto ben definito? Rendi il tuo metodo private e / o pensa a come puoi rendere disponibile il contesto richiesto ben definito per riutilizzarlo attraverso un altro metodo di wrapping protected .

Ecco perché sostengo di usare private con parsimonia. E per non confondere private con final . - Se l'implementazione di un metodo è vitale per il contratto generale della classe e quindi non deve essere sostituita / sostituita, rendila final !

Per i campi, private non è davvero male. Finché i campi possono essere ragionevolmente "utilizzati" con metodi appropriati (cioè non getXX() o setXX() !).

    
risposta data 11.03.2016 - 14:47
fonte
-1

Do you know about an important use case where private instead of protected is a good tool, or would two options "protected & public" be enough for OOP languages?

Privato : quando hai qualcosa che non sarà mai utile per le sottoclassi da chiamare o sostituire.

Protetto : quando hai qualcosa che ha un'implementazione / costante specifica per sottoclasse.

Un esempio:

public abstract Class MercedesBenz() extends Car {
  //Might be useful for subclasses to know about their customers
  protected Customer customer; 

  /* Each specific model has its own horn. 
     Therefore: protected, so that each subclass might implement it as they wish
  */
  protected abstract void honk();

  /* Taken from the car class. */
  @Override
  public void getTechSupport(){
     showMercedesBenzHQContactDetails(customer);
     automaticallyNotifyLocalDealer(customer);
  }

  /* 
     This isn't specific for any subclass.
     It is also not useful to call this from inside a subclass,
     because local dealers only want to be notified when a 
     customer wants tech support. 
   */
  private void automaticallyNotifyLocalDealer(){
    ...
  }
}
    
risposta data 18.03.2016 - 11:12
fonte
-2

È stato difficile per me capire questo argomento, quindi mi piacerebbe condividere un pezzo della mia esperienza:

  • Che cos'è il campo protetto ? È nient'altro di un campo, a cui non è possibile accedere al di fuori di una classe, ad esempio pubblicamente come questo: $classInstance->field . E il trucco è "questo è tutto". I bambini della tua classe avranno un accesso completo perché è la loro parte interna legittima.
  • Che cos'è il campo privato ? È un " true private " per la tua classe e la tua implementazione personale di questa classe. "Tenere fuori dalla portata dei bambini", proprio come sulla bottiglia di una medicina. Avrai la garanzia che è irrecuperabile con i derivati della tua classe, i tuoi metodi - quando chiamati - avranno esatti ciò che hai dichiarato

AGGIORNAMENTO: un esempio pratico di un compito reale che ho risolto. Eccolo: hai un token, come USB o LPT (era il mio caso), e hai un middleware. Il token ti chiede un codice PIN, si apre se è corretto e puoi inviare una parte crittografata e un numero di chiavi da decifrare. Le chiavi sono memorizzate in token, non puoi leggerle, usale solo. E c'erano le chiavi temporanee per una sessione, firmate da una chiave in un token, ma memorizzate in un middleware stesso. La chiave temp non avrebbe dovuto fuoriuscire eveywhere all'esterno, solo per esistere a livello di driver. E ho utilizzato un campo privato per memorizzare questa chiave temporanea e alcuni dati relativi alla connessione hardware. Quindi nessuna derivata è stata in grado di utilizzare non solo un'interfaccia pubblica, ma anche alcune subroutine protette "utili" che ho creato per un'attività, ma non sono state in grado di aprire una cassastrong con le chiavi e l'interazione HW. Ha senso?

    
risposta data 11.03.2016 - 21:24
fonte

Leggi altre domande sui tag