2009-03-22 18 views
5

Ho una classe con molti membri di tipo built-in con accesso di lettura/scrittura. Dovrei renderli membri pubblici e fornire metodi get/set per ognuno? Che ne dici di strutture?Accessors vs membri pubblici

risposta

13

Se ci sono invariants è necessario conservare, quindi sì. Altrimenti, non preoccuparti.

+1

Per i downvoters: ho preso personalmente il consiglio da Stroustrup: http://www.artima.com/intv/goldilocks3.html "Bjarne Stroustrup: la mia regola generale è che dovresti avere una vera classe con un'interfaccia e una nascosta rappresentazione se e solo se si può considerare un'invarianza per la classe. " –

+0

Lo fa definitivamente. Più avanti nello stesso testo: "Sì. Se ogni dato può avere qualsiasi valore, non ha molto senso avere una classe, prendere una singola struttura dati con un nome e un indirizzo. Ogni stringa è un buon nome, e qualsiasi stringa è un buon indirizzo.Se è quello che è, è una struttura –

+0

Continua: "Non avere nulla di privato. Non fare sciocchezze come avere un nome e un campo di indirizzo nascosti con get_name e set_address e get_name e set_name. O peggio ancora, creare una classe base virtuale con le funzioni virtuali get_name e set_name e così via. " –

4

In primo luogo, se la tua classe ha un sacco di dati mamebers, probabilmente non è ben progettata. Potrebbe essere necessario prendere in considerazione la suddivisione in più classi o la memorizzazione dei dati in strutture come le mappe.

Per quanto riguarda la fornitura di accessor, la domanda è se si desidera modificare l'accesso, eventualmente prevenirlo. Se la risposta è sì, allora è necessario accedere alle funzioni. D'altra parte, se la tua classe è in realtà solo una borsa di bit, senza alcun comportamento, allora rendila una struttura.

0

L'utilizzo dei metodi get/set per i membri dati privati ​​/ protetti è una progettazione errata.

Fa sì che il codice client dipenda dai dettagli di implementazione della classe.

Le modifiche nella classe causano modifiche nel codice cliente.

Tuttavia, è possibile utilizzare i metodi get/set per i membri pubblici. Ma è sempre bene evitarli.

+0

Perché -3 downvoting? – anand

+1

L'ho inviato, quindi è stato almeno 4 downvotes :) Seriamente, ho pensato che fosse una conoscenza comune che i getter/setter sono un cattivo progetto. Spaventoso. –

+0

OK la domanda era se getter/setter possono essere utilizzati? È un cattivo design la maggior parte delle volte e quello a cui ho risposto. Dalla maggior parte delle risposte sopra è la stessa conclusione. Non sono sicuro che sia una conoscenza comune per tutti. – anand

19

L'intera ragione per avere accessor (getter) e modificatori (setter) è di fornirti un livello aggiuntivo di riferimento indiretto.

Questo livello aggiuntivo di riferimento indiretto consente di fornire una visualizzazione di sola lettura della variabile a un'interfaccia pubblica, pur non consentendo la modifica del membro dati. Potresti ancora usare un setter privato o protetto.

I setter consentono di eseguire speciali verifiche, convalide e correzioni degli errori quando viene impostato un valore. Ad esempio setDirectory (const std :: string & strPath), è possibile assicurarsi che vi sia una barra di chiusura se l'utente non ne ha specificato uno. Questo assicura che lo stato della tua classe sarà sempre valido.

I getter possono anche proteggere i membri dall'averli esposti per consentire loro di indicarli. Non consentendo loro di indicarli dall'esterno, puoi assicurarti che se il tuo oggetto non rientra nello scope non causerà un crash.

Il livello aggiuntivo di riferimento indiretto per getter/setter consente inoltre di modificare il membro dati che incapsulano.

Con un getter è inoltre possibile ottenere visualizzazioni diverse dei dati, ad esempio: getMinutes, quando il membro dati viene effettivamente memorizzato in pochi secondi.

Non è questo il motivo per usarli, ma un piacevole effetto collaterale di utilizzare getter e setter è che è possibile impostare un punto di interruzione all'interno del vostro modificatore per esempio per vedere esattamente quando è cambiato.

Se dovresti usarli o meno è una chiamata di giudizio basata sul tuo bisogno. Se hai così tanti membri che è un enorme problema fornire getter e impostazioni, potresti prendere in considerazione l'archiviazione dei membri dei dati in una struttura e utilizzare invece quella struttura all'interno della classe. Potresti anche fornire getter/setter per un oggetto per l'intera struttura in una sola volta.

1

Si dovrebbe usare membri dati pubblici solo

  • in strutture, che non si espongono al codice del client (ad es.bind-style funtori) - è inutile proteggere le strutture che nessuno al di fuori potrà mai ottenere
  • se i loro tipi incapsulano la logica di insieme/far loro (ad esempio, se si crea un ObservableAttribute classe)
  • se sono const membri. in una struttura immutabile (non si può fare molto, tranne per leggere loro se sono immutabili)

Se si crea un membro di dati pubblici, bisogna essere sicuri che il suo valore è completamente ortogonale con gli altri membri la classe. Ad esempio., Si disattiva possibilità future di

  • osservando le modifiche al membro
  • rendendo il membro riprodurre qualsiasi parte della classe invariante
  • disabilitare l'accesso al membro
  • cambiando l'attuazione del membro (ad esempio, calcolato vs. cache memorizzato) se le prestazioni lo richiedono
Problemi correlati