Domanda

È normale modificare gli argomenti setter? Immaginiamo di avere il metodo setString. E vogliamo davvero mantenere una forma ritagliata della corda. Quindi una stringa con spazi finali non è valida, ma non vogliamo generare un'eccezione.

Qual è la soluzione migliore? Per tagliare il valore nel setter, ad esempio

public void setString(String string) {
    this.string = string.trim();
}

Oppure taglialo nel chiamante (più di una volta), ad esempio

object.setString(string.trim());

O forse qualcos'altro?

È stato utile?

Soluzione

Sì. Dopotutto, i setter sono progettati per questo tipo di cose! Per controllare e sanificare i valori scritti nei campi;)

Altri suggerimenti

Totalmente. Ecco un esempio: supponiamo di avere un programma di ingegneria con diversi tipi di unità di misura. Mantenete i valori interni in un sistema di misurazione, ma convertite da tutti gli altri nel setter e convertite nuovamente in getter, ad es .:

public double UserTemperature
{
  get
  {
    return Units.Instance.ConvertFromSystem(UnitType.Temperature, temperature);
  }
  set  
  {
    double v = Units.Instance.ConvertToSystem(UnitType.Temperature, value);
    if (temperature != v)
    {
      temperature = v;
      Changed("SystemTemperature");
      Changed("UserTemperature");
    }
  }
}

Sì, certo. Fai solo attenzione a controllare NULL prima di applicare qualsiasi metodo (come trim ()).

Esistono due scuole: una dice che va bene controllare il parametro in setter (stile scuola) e la seconda dice che i bean non dovrebbero contenere alcuna logica e solo dati (stile aziendale).

Credo di più nella seconda. Quanto spesso guardi all'implementazione dei tuoi fagioli? getUser dovrebbe generare qualche eccezione o restituire null?

Quando metti la logica nel tuo setter e getter, rendi più difficile capire cosa sta succedendo poiché molte persone non guarderanno mai alla sua implementazione. Se non sei d'accordo, ti esorto a esaminare ogni setter e implementazione getter prima di usarlo solo per verificare se non è solo un bean.

A prima vista sembra violare il principio del minimo stupore . Se sono un utente della tua classe, mi aspetto che un setter faccia esattamente quello che gli dico. Darei un'eccezione nel setter per costringere gli utenti a tagliare l'input.

L'altra (migliore?) alternativa è cambiare il nome del metodo in trimAndSetString. In questo modo, non è sorprendente il comportamento di tagliare l'input.

Correggimi se sbaglio, ma mi sembra logico che il setter debba mantenere questo tipo di logica. Se il setter sta semplicemente assegnando un valore a un var interno senza verificarlo, allora perché non esporre il var stesso?

Questo è esattamente il motivo per cui usi setter anziché esporre i campi degli oggetti a tutto il mondo.

Considera una classe che contiene un angolo intero che dovrebbe essere compreso tra 0 e 359 inclusi.

Se si espone il campo, le funzioni di chiamata possono impostarlo su quello che vogliono e questo romperebbe il contratto specificato dall'API. È anche probabile che rompa la tua funzionalità da qualche parte lungo la traccia perché il tuo codice è scritto per assumere un certo intervallo per quella variabile.

Con un setter, ci sono diverse cose che puoi fare. Uno è sollevare un'eccezione per indicare che è stato passato un valore non valido, ma a mio avviso non sarebbe corretto (in questo caso). È probabile che sia più utile se modifichi il valore di input su qualcosa compreso tra 0 e 359, ad esempio con:

actualVal = passedValue % 360;

Fintanto che è specificato nell'interfaccia (API), è perfettamente valido. In effetti, anche se non lo specifichi, sei comunque libero di fare tutto ciò che desideri poiché il chiamante ha violato il contratto (passando un valore al di fuori dell'intervallo). Tendo a seguire la regola di "sanificare il tuo contributo il prima possibile".

Nel tuo caso specifico, fintanto che specifichi che la stringa è memorizzata nel formato tagliato, non c'è motivo per cui i chiamanti si lamentino (hai già dichiarato che tale stringa non è valida). È meglio in termini di dimensioni del codice (non velocità) farlo nel setter piuttosto che in ogni parte di codice che chiama il setter. Garantisce inoltre che la stringa sia memorizzata come previsto: non esiste alcuna garanzia che un chiamante non memorizzi accidentalmente (o intenzionalmente) una stringa non tagliata.

Sì. È una caratteristica del design orientato agli oggetti è che il chiamante può trattare la tua classe come una scatola nera. Quello che fai dentro è la tua attività, purché il comportamento dell'interfaccia sia documentato e logico.

Mentre persone diverse hanno filosofie diverse, suggerirei che i setter di proprietà siano appropriati solo nei casi in cui imposteranno un aspetto dello stato dell'oggetto in modo che corrisponda al valore indicato e forse notifichino a chiunque si preoccupi del cambiamento, ma non altrimenti influisce sullo stato dell'oggetto (è del tutto corretto per un setter di proprietà modificare il valore di una proprietà di sola lettura se tale proprietà è definita in termini di stato associato al setter di proprietà; ad esempio, la proprietà Right di sola lettura di un controllo può essere definita in termini di Bounds ). I setter di proprietà dovrebbero generare un'eccezione se non possono eseguire l'operazione indicata.

Se si desidera consentire a un client di modificare lo stato di un oggetto in qualche modo non rispettando la descrizione sopra, si dovrebbe usare un metodo piuttosto che una proprietà. Se si chiama Foo.SetAngle (500) , ci si aspetterebbe ragionevolmente che il metodo utilizzerà il parametro indicato per impostare l'angolo, ma la proprietà Angle potrebbe non restituire l'angolo nella stessa forma in cui è stato impostato (ad esempio, potrebbe restituire 140). D'altra parte, se Angle è una proprietà di lettura / scrittura, ci si aspetterebbe che la scrittura di un valore di 500 sia vietata oppure causerebbe la rilettura del valore di 500. Se si volesse avere l'oggetto memorizza un angolo nell'intervallo da 0 a 359, l'oggetto potrebbe anche avere una proprietà di sola lettura chiamata BaseAngle che restituirà sempre un angolo in quella forma.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top