Come accedereste alle proprietà degli oggetti dall'interno di un metodo dell'oggetto? [chiuso]


96

Qual è il modo "purista" o "corretto" per accedere alle proprietà di un oggetto dall'interno di un metodo oggetto che non è un metodo getter / setter?

So che dall'esterno dell'oggetto dovresti usare un getter / setter, ma dall'interno faresti semplicemente:

Giava:

String property = this.property;

PHP:

$property = $this->property;

o faresti:

Giava:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Perdonami se il mio Java è un po 'spento, è passato un anno da quando ho programmato in Java ...

MODIFICARE:

Sembra che le persone presumano che io parli solo di variabili / proprietà private o protette. Quando ho imparato l'OO mi è stato insegnato a usare getter / setter per ogni singola proprietà anche se era pubblica (e in realtà mi è stato detto di non rendere pubblica alcuna variabile / proprietà). Quindi, potrei partire da una falsa supposizione sin dall'inizio. Sembra che le persone che rispondono a questa domanda stiano forse dicendo che dovresti avere proprietà pubbliche e che quelle non hanno bisogno di getter e setter, il che va contro ciò che mi è stato insegnato e ciò di cui stavo parlando, anche se forse questo deve essere discusso come bene. Questo è probabilmente un buon argomento per una domanda diversa però ...

Risposte:


62

Questo ha un potenziale di guerra religiosa, ma mi sembra che se stai usando un getter / setter, dovresti usarlo anche internamente - l'uso di entrambi porterà a problemi di manutenzione lungo la strada (ad esempio qualcuno aggiunge il codice a un setter che ha bisogno da eseguire ogni volta che la proprietà viene impostata e la proprietà viene impostata internamente senza che il setter venga chiamato).


non sta facendo nient'altro in un setter se non impostare il valore della proprietà un esempio di utilizzo errato in Java.
euphoria83

1
@ euphoria83 Forse, ma questo non impedisce che accada.
Greg Hurlman

Sono d'accordo con la risposta originale. Tuttavia, ricorda che se stai impostando o ottenendo qualcosa di privato all'interno della classe o dell'oggetto, devi assicurarti che il getter / setter non sia ciclico o ridondante in qualche modo che causa il fallimento del tuo codice. Se non puoi utilizzare il getter / setter, accedilo direttamente. (Es. Il tuo getter / setter accede a un metodo secondario (privato / protetto) per manipolare i dati.)
Rick Mac Gillis

43

Personalmente, sento che è importante rimanere coerenti. Se hai getter e setter, usali. L'unica volta in cui accedo direttamente a un campo è quando la funzione di accesso ha molte spese generali. Potrebbe sembrare che tu stia gonfiando il tuo codice inutilmente, ma sicuramente può farti risparmiare un sacco di mal di testa in futuro. L'esempio classico:

In seguito, potresti voler cambiare il modo in cui funziona quel campo. Forse dovrebbe essere calcolato al volo o forse vorresti usare un tipo diverso per il negozio di supporto. Se stai accedendo direttamente alle proprietà, una modifica del genere può rompere un sacco di codice in un sol colpo.


26

Sono abbastanza sorpreso di quanto sia unanime il sentimento getterse che i setter siano bravi e bravi. Suggerisco l'articolo incendiario di Allen Holub " Getters And Setters Are Evil ". Certo, il titolo è per il valore shock, ma l'autore fa punti validi.

In sostanza, se hai getterse settersper ogni campo privato, stai rendendo quei campi tanto buoni quanto pubblici. Sarebbe molto difficile cambiare il tipo di un campo privato senza effetti a catena in ogni classe che lo chiama getter.

Inoltre, da un punto di vista strettamente OO, gli oggetti dovrebbero rispondere a messaggi (metodi) che corrispondono alla loro (si spera) unica responsabilità. La stragrande maggioranza getterse settersnon ha senso per i loro oggetti costitutivi; Pen.dispenseInkOnto(Surface)ha più senso per me diPen.getColor() .

Getter e setter incoraggiano anche gli utenti della classe a chiedere all'oggetto alcuni dati, eseguire un calcolo e quindi impostare qualche altro valore nell'oggetto, meglio noto come programmazione procedurale. Faresti meglio a dire semplicemente all'oggetto di fare ciò che stavi per fare in primo luogo; noto anche come idioma dell'esperto di informazioni .

Getter e setter, tuttavia, sono mali necessari al confine degli strati: interfaccia utente, persistenza e così via. L'accesso limitato agli interni di una classe, come la parola chiave friend di C ++, l'accesso protetto al pacchetto di Java, l'accesso interno di .NET e il modello di classe Friend possono aiutarti a ridurre la visibilità dei getterssetter e solo a coloro che ne hanno bisogno.


19

Dipende da come viene utilizzata la proprietà. Ad esempio, supponi di avere un oggetto studente con una proprietà name. È possibile utilizzare il metodo Get per estrarre il nome dal database, se non è già stato recuperato. In questo modo riduci le chiamate non necessarie al database.

Supponiamo ora di avere un contatore intero privato nel tuo oggetto che conta il numero di volte in cui il nome è stato chiamato. È possibile non utilizzare il metodo Get dall'interno dell'oggetto perché produrrebbe un conteggio non valido.


Se l'oggetto Student è un oggetto business / dominio, stai ora mescolando i dettagli dell'infrastruttura. Idealmente, un oggetto business / dominio dovrebbe riguardare solo la logica business / dominio.
moffdub

Cosa succede se aggiungi una sorta di booleano al getter come: PHP: public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } return $ this-> name; } e quindi dall'interno dell'Oggetto stesso, se si chiama get name, è possibile evitare che aumenti di: PHP: $ name = $ this-> getName (false); Sto solo esagerando qui?
cmcculloh

14

PHP offre una miriade di modi per gestirlo, inclusi metodi magici __gete __set, ma preferisco getter e setter espliciti. Ecco perché:

  1. La convalida può essere inserita in setter (e getter per quella materia)
  2. Intellisense funziona con metodi espliciti
  3. Nessun dubbio se una proprietà è di sola lettura, solo scrittura o lettura-scrittura
  4. Il recupero delle proprietà virtuali (cioè i valori calcolati) ha lo stesso aspetto delle proprietà normali
  5. È possibile impostare facilmente una proprietà dell'oggetto che non è mai effettivamente definita da nessuna parte, che quindi non viene documentata

13

Sto solo esagerando qui?

Forse ;)

Un altro approccio potrebbe essere quello di utilizzare un metodo privato / protetto per eseguire effettivamente l'operazione di recupero (memorizzazione nella cache / db / ecc.) E un wrapper pubblico che incrementa il conteggio:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

e poi dall'interno dell'oggetto stesso:

PHP:

$name = $this->_getName();

In questo modo puoi ancora usare quel primo argomento per qualcos'altro (come inviare un flag per se utilizzare o meno i dati memorizzati nella cache qui forse).


12

Devo mancare il punto qui, perché dovresti usare un getter all'interno di un oggetto per accedere a una proprietà di quell'oggetto?

Portando questo alla sua conclusione, il getter dovrebbe chiamare un getter, che dovrebbe chiamare un getter.

Quindi direi che all'interno di un metodo oggetto accedere direttamente a una proprietà, soprattutto visto che chiamare un altro metodo in quell'oggetto (che accederà comunque direttamente alla proprietà e poi lo restituirà) è solo un esercizio inutile e dispendioso (o ho frainteso la domanda ).


Sono stato spinto dalla stessa esigenza che avevi tu di commentare ... Inoltre non è stato risposto chiuso;)
Egg Vans

8

Il modo OO purista è quello di evitare entrambi e seguire la Legge di Demetra usando l' approccio Tell Don't Ask .

Invece di ottenere il valore della proprietà dell'oggetto, che accoppia strettamente le due classi, usa l'oggetto come parametro es

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

Dove la proprietà era un tipo nativo, ad esempio int, usa un metodo di accesso, chiamalo per il dominio del problema e non per il dominio di programmazione.

  doSomethingWithProperty( this.daysPerWeek() ) ;

Questi ti permetteranno di mantenere l'incapsulamento ed eventuali post-condizioni o invarianti dipendenti. Puoi anche utilizzare il metodo setter per mantenere eventuali pre-condizioni o invarianti dipendenti, tuttavia non cadere nella trappola di nominarli setter, torna al principio di Hollywood per la denominazione quando usi l'idioma.


8

È preferibile utilizzare i metodi di accesso, anche all'interno dell'oggetto. Ecco i punti che mi vengono subito in mente:

  1. Dovrebbe essere fatto nell'interesse di mantenere la coerenza con gli accessi effettuati dall'esterno dell'oggetto.

  2. In alcuni casi, questi metodi di accesso potrebbero fare di più che accedere al campo; potrebbero fare qualche elaborazione aggiuntiva (questo è raro però). Se questo è il caso, accedere direttamente al campo significherebbe che ti manca quell'ulteriore elaborazione e il tuo programma potrebbe andare storto se questa elaborazione deve essere sempre eseguita durante quegli accessi.


8

Se intendi "la maggior parte degli incapsulamenti" con "purista", in genere dichiaro tutti i miei campi come privati ​​e quindi uso "this.field" dall'interno della classe stessa. Per altre classi, comprese le sottoclassi, accedo allo stato dell'istanza utilizzando i getter.


7

Ho scoperto che l'uso di setter / getter ha reso il mio codice più facile da leggere. Mi piace anche il controllo che dà quando altre classi usano i metodi e se cambio i dati la proprietà memorizzerà.


7

Campi privati ​​con proprietà pubbliche o protette. L'accesso ai valori dovrebbe passare attraverso le proprietà ed essere copiato in una variabile locale se verranno utilizzati più di una volta in un metodo. Se e SOLO se hai il resto della tua applicazione così totalmente ottimizzato, scosso e altrimenti ottimizzato in modo che l'accesso ai valori passando attraverso le loro proprietà associate è diventato un collo di bottiglia (e questo non accadrà MAI, lo garantisco) dovresti anche iniziare considerare di lasciare che qualcosa di diverso dalle proprietà tocchi direttamente le loro variabili di supporto.

Gli sviluppatori .NET possono utilizzare le proprietà automatiche per applicare ciò poiché non è possibile nemmeno vedere le variabili di supporto in fase di progettazione.


7

Dipende. È più una questione di stile che altro e non esiste una regola rigida.


7

Posso sbagliarmi perché sono autodidatta, ma NON utilizzo MAI proprietà pubbliche nelle mie classi Java, sono sempre private o protette, quindi il codice esterno deve accedere da getter / setter. È meglio per scopi di manutenzione / modifica. E per il codice della classe interna ... Se il metodo getter è banale, uso direttamente la proprietà, ma utilizzo sempre i metodi setter perché potrei facilmente aggiungere codice per attivare gli eventi se lo desidero.


7

Se non modifico la proprietà, userò un metodo pubblico a get_property()meno che non sia un'occasione speciale come un oggetto MySQLi all'interno di un altro oggetto, nel qual caso renderò pubblica la proprietà e farò riferimento ad essa come$obj->object_property .

All'interno dell'oggetto è sempre $ this-> proprietà per me.


5

Bene, sembra che con l'implementazione predefinita delle proprietà C # 3.0, la decisione sia presa per te; DEVI impostare la proprietà utilizzando il setter di proprietà (possibilmente privato).

Personalmente uso solo il member-behind privato quando non farlo causerebbe la caduta dell'oggetto in uno stato meno che desiderabile, come durante l'inizializzazione o quando è coinvolto il caching / caricamento lento.


5

Mi piace la risposta di cmcculloh , ma sembra che la risposta più corretta sia quella di Greg Hurlman . Usa sempre getter / setter se hai iniziato a usarli dall'inizio e / o sei abituato a lavorare con loro.

Per inciso, personalmente trovo che l'uso di getter / setter renda il codice più facile da leggere e da eseguire il debug in seguito.


4

Come affermato in alcuni commenti: a volte dovresti, a volte non dovresti. La parte migliore delle variabili private è che sei in grado di vedere tutti i posti in cui vengono utilizzate quando cambi qualcosa. Se il tuo getter / setter fa qualcosa di cui hai bisogno, usalo. Se non importa, decidi tu.

Si potrebbe fare il caso opposto che se usi il getter / setter e qualcuno cambia il getter / setter deve analizzare tutti i posti in cui il getter e il setter sono usati internamente per vedere se rovina qualcosa.

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.