Quando utilizzare una variabile di istanza di un oggetto rispetto al passaggio di un argomento al metodo


93

Come decidi tra il passaggio di argomenti a un metodo e il semplice fatto di dichiararli come variabili di istanza dell'oggetto visibili a tutti i metodi dell'oggetto?

Preferisco mantenere le variabili di istanza in un elenco alla fine della classe, ma questo elenco si allunga man mano che il mio programma cresce. Immagino che se una variabile viene passata abbastanza spesso dovrebbe essere visibile a tutti i metodi che ne hanno bisogno, ma poi mi chiedo, "se tutto è pubblico non ci sarà bisogno di passare nulla!"


1
Se hai degli esempi specifici, potresti ottenere risposte più direttamente utili
brabster

Risposte:


55

Dato che ti riferisci a variabili di istanza, presumo che tu stia lavorando in un linguaggio orientato agli oggetti. In una certa misura, quando usare le variabili di istanza, come definirne l'ambito e quando usare le variabili locali è soggettivo, ma ci sono un paio di regole pratiche che puoi seguire ogni volta che crei le tue classi.

  • Le variabili di istanza sono generalmente considerate attributi di una classe. Pensa a questi come aggettivi dell'oggetto che verrà creato dalla tua classe. Se i dati della tua istanza possono essere usati per descrivere l'oggetto, allora è probabilmente sicuro scommettere che è una buona scelta per i dati dell'istanza.

  • Le variabili locali vengono utilizzate nell'ambito dei metodi per aiutarli a completare il loro lavoro. Di solito, un metodo dovrebbe avere lo scopo di ottenere alcuni dati, restituire alcuni dati e / o elaborare / eseguire un algoritmo su alcuni dati. A volte, è utile pensare alle variabili locali come modi per aiutare un metodo a passare dall'inizio alla fine.

  • L'ambito della variabile di istanza non è solo per la sicurezza, ma anche per l'incapsulamento. Non dare per scontato che "l'obiettivo dovrebbe essere quello di mantenere private tutte le variabili". In caso di ereditarietà, rendere le variabili protette di solito è una buona alternativa. Piuttosto che contrassegnare tutti i dati dell'istanza come pubblici, crei getter / setter per coloro a cui è necessario accedere al mondo esterno. Non renderli tutti disponibili, solo quelli di cui hai bisogno. Ciò avverrà durante tutto il ciclo di vita dello sviluppo: è difficile indovinarlo sin dall'inizio.

Quando si tratta di passare dati a una classe, è difficile dire che quello che stai facendo è una buona pratica senza vedere del codice. A volte va bene operare direttamente sui dati dell'istanza; altre volte no. Secondo me, questo è qualcosa che viene fornito con l'esperienza: svilupperai un po 'di intuizione man mano che le tue capacità di pensiero orientato agli oggetti migliorano.


La mia risposta sarebbe aggiungere questa risposta alla risposta di H-Man2 (a vita). Dovrebbe essere un attributo membro se e solo se è uno stato persistente dell'oggetto. Cioè, il valore ha senso da solo al di fuori dell'ambito dello stack del metodo corrente.
David Rodríguez - dribeas

La mia reazione istintiva è essere d'accordo con David e H-MAn2. Tuttavia sto leggendo "codice pulito" di Robert c Martin e nel capitolo 3 egli effettua il refactoring del codice per spostare qualcosa da un parametro di metodo a una variabile membro, perché avere molti parametri è un male. A conti fatti, immagino che se la tua classe ha una sola responsabilità, la durata dell'oggetto è la stessa della durata di quel calcolo, quindi forse la risposta effettiva è che se devi fare questa domanda, la tua classe è troppo grande?
Andy

@ DavidRodríguez-dribeas cosa intendi per stack di metodi?
impegnato e

@committedand ricam: se il valore sopravvive alla chiamata di funzione corrente
David Rodríguez - dribeas

46

Principalmente questo dipende dalla durata dei dati archiviati nella variabile. Se i dati vengono utilizzati solo durante un calcolo, passarli come parametro. Se i dati sono legati alla durata dell'oggetto, utilizzare una variabile di istanza.

Quando il tuo elenco di variabili diventa troppo lungo, forse è un buon punto pensare a refactoring di alcune parti della classe in una nuova classe.


21

A mio parere, le variabili di istanza sono necessarie solo quando i dati verranno utilizzati tra le chiamate.

Ecco un esempio:

myCircle = myDrawing.drawCircle(center, radius);

Ora immaginiamo che la classe myDrawing utilizzi 15 funzioni di supporto per creare l'oggetto myCircle e ciascuna di queste funzioni avrà bisogno del centro e del raggio. Non dovrebbero comunque essere impostati come variabili di istanza della classe myDrawing. Perché non saranno mai più necessari.

D'altra parte, la classe myCircle dovrà memorizzare sia il centro che il raggio come variabili di istanza.

myCircle.move(newCenter);
myCircle.resize(newRadius);

Affinché l'oggetto myCircle sappia qual è il raggio e il centro quando vengono effettuate queste nuove chiamate, devono essere archiviate come variabili di istanza, non solo passate alle funzioni che ne hanno bisogno.

Quindi, fondamentalmente, le variabili di istanza sono un modo per salvare lo "stato" di un oggetto. Se una variabile non è necessaria per conoscere lo stato di un oggetto, non dovrebbe essere una variabile di istanza.

E per quanto riguarda rendere tutto pubblico. Potrebbe semplificarti la vita in questo momento. Ma tornerà a perseguitarti. Per favore, non farlo.


Tuttavia, potresti semplicemente definire move per utilizzare i parametri (oldCenter, newCenter).
obesechicken13

4

A PARER MIO:

Se la variabile fa parte dello stato dell'istanza, dovrebbe essere una variabile di istanza - classinstance HAS-A instancevariable.

Se mi ritrovo a passare ripetutamente qualcosa nei metodi di un'istanza, o ho scoperto di avere un gran numero di variabili di istanza, probabilmente proverei a guardare il mio progetto nel caso mi fossi perso qualcosa o avessi fatto una cattiva astrazione da qualche parte.

Spero che sia d'aiuto


3

Ovviamente è facile mantenere un grande elenco di variabili pubbliche nella classe. Ma anche intuitivamente, puoi dire che questa non è la strada da percorrere.

Definisci ogni variabile subito prima di usarla. Se una variabile supporta la funzione di un metodo specifico, utilizzala solo nell'ambito del metodo.

Pensa anche alla sicurezza, una variabile di classe pubblica è suscettibile a modifiche indesiderate dal codice "esterno". Il tuo obiettivo principale dovrebbe essere quello di mantenere tutte le variabili private, e qualsiasi variabile che non lo sia, dovrebbe avere un'ottima ragione per esserlo.

Riguardo al passaggio dei parametri in cima allo stack, questo può diventare brutto molto velocemente. Una regola pratica è mantenere le firme dei metodi pulite ed eleganti. Se vedi molti metodi che utilizzano gli stessi dati, decidi se è abbastanza importante per essere un membro della classe e, in caso contrario, effettua il refactoring del codice per renderlo più sensato.

Si riduce al buon senso. Pensa esattamente dove e perché stai dichiarando ogni nuova variabile, quale dovrebbe essere la sua funzione e da lì prendi una decisione in merito all'ambito in cui dovrebbe vivere.


Spesso desideri che i metodi siano pubblici in modo da poterli unit testare.
obesechicken13
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.