2012-09-07 14 views
21

Se si dispone di una classe cliente con un costruttore sovraccarico (predefinito e uno con parametri) qual è il modo corretto per impostare i membri della classe nel costruttore Sovraccaricato? Usando "questo" riferimenti o usando i metodi setter?Class best practice

Semplicemente non ero sicuro di quale fosse il metodo corretto.

public class Customer { 

private String firstName; 
private String lastName; 
private int age; 

public Customer() {} 

//This Way 
public Customer(String firstName, String lastName, int age) 
{ 
    this.firstName = firstName; 
    this.lastName = lastName; 
    this.age = age; 
} 

// Or this way? 
    public Customer(String firstName, String lastName, int age) 
{ 
    setFirstName(firstName); 
    setLastName(lastName); 
    setAge(age); 
} 



/** 
* @return the firstName 
*/ 
public String getFirstName() { 
    return firstName; 
} 

/** 
* @param firstName the firstName to set 
*/ 
public void setFirstName(String firstName) { 
    this.firstName = firstName; 
} 

/** 
* @return the lastName 
*/ 
public String getLastName() { 
    return lastName; 
} 

/** 
* @param lastName the lastName to set 
*/ 
public void setLastName(String lastName) { 
    this.lastName = lastName; 
} 

/** 
* @return the age 
*/ 
public int getAge() { 
    return age; 
} 

/** 
* @param age the age to set 
*/ 
public void setAge(int age) { 
    this.age = age; 
} 

}

risposta

27

Il primo (utilizzando this.) è probabilmente più sicuro e più diretto. Considera se una futura sottoclasse ha sovrascritto i metodi setter - questo potrebbe causare un comportamento molto inaspettato.

Se la tua classe è definitiva, questo è irrilevante ed è un lavaggio.

+4

Questa è l'unica risposta sensata finora. In effetti, diversi strumenti per la rimozione dei residui avvertiranno di chiamare i metodi non definitivi dai costruttori proprio per questo problema. (Se la classe non è definitiva ma i metodi setter sono altrettanto validi.) –

+0

@KumarVivekMitra - Non mi piace la tua risposta, come indica il mio commento. –

+0

@TedHopp, per favore leggi di nuovo la mia risposta ... penso che entrambi stessimo parlando della stessa cosa ... ancora mi lasci di nuovo scrivere qui ... Penso che tu stia adottando il principio "OCP" ,,, Le classi sono aperte per l'estensione, ma chiuse per la modifica .... E come so 'I costruttori non possono essere ereditati e quindi NON POSSONO essere ignorati, quindi è immutabile ....' –

0

In sostanza, non v'è alcuna differenza, tranne per la convalida.

Da una parte, se il setter convalida nuovi valori basati solo sui nuovi valori (non dipendono dallo stato dell'oggetto), la chiamata al setter evita la duplicazione della logica di convalida.

D'altra parte, se la convalida di un setter controlla altre proprietà, allora si deve essere sicuri che le proprietà necessarie siano già impostate prima di chiamare quel setter o assegnare direttamente la proprietà.

0

Il modo di accesso diretto è più veloce (7 volte più veloce se la memoria mi serve correttamente) ma il secondo è "più sicuro" nel caso in cui alcune regole speciali assegnino quei valori o concatenamento di assegnazione (in cui si assegna un secondo campo dal setter di un altro) dove implementato negli accessor, a meno che, naturalmente, non si voglia escludere tali regole/concatenazioni quando l'assegnazione viene eseguita dal costruttore.

Quindi, in breve, dipende dalle vostre esigenze ma quelle sono le preoccupazioni principali che posso pensare.

+0

Il secondo metodo è tutt'altro che "più sicuro" a meno che i metodi setter (o la classe) non siano "final". Cosa succede se una sottoclasse sovrascrive il setter e non riesce a chiamare fino alla superclasse? –

+1

Se stai creando una sottoclasse di un tipo e stai sovrascrivendo i metodi setter senza impostare nulla con loro, allora hai un problema molto più grande che decidere quale costruttore usare. –

+0

@TedHopp Stavo scrivendo una lunga descrizione di ciò che Jordan White ha detto così lascerò perdere :) – JTMon

1

La migliore risposta sarebbe "dipende". Generalmente, non è necessario utilizzare setter a meno che i setter facciano qualcosa di più simile a un calcolo prima di impostare il valore. Tuttavia, se i setter impostano solo il valore direttamente, allora this è probabilmente il migliore per te. Al contrario, i setter sono usati per la convalida e roba del genere, se usi this, ti perderai.

2

relativo non circa, che è un modo migliore per farlo, ma ciò che si desidera fuori di esso ......

- Se si desidera che il classe di essere mutable, poi andare con setters.

- Se si desidera che il classe di essere Immutable allora penso utilizzando this, è una scelta migliore.

Penso che l'utilizzo di this, sia adatto in luoghi, in cui si ricevono alcuni dati da un server Web o da una fonte, quindi li si archivia in una raccolta in forma di istanze di una classe personalizzata .....

Esempio:

  • Creare un allievo del codice categoria,

  • Come si effettua una richiesta a qualche web-service, si otterrà la risposta, per esempio :JSON ..

  • Analizzarlo, quindi creare un'istanza di Studente e archiviarlo in una raccolta ..

    esempio:

    ArrayList<Student> arList = new ArrayList<Student>();

    arList.add(new Student(name,rollNos,class,marks));

+0

Chiamare un metodo non finale (come un setter) da un costruttore non è una buona idea. Vedi, ad esempio, [questo articolo] (http://www.informit.com/articles/article.aspx?p=20521). –

+0

@TedHopp Penso che tu stia adottando il principio 'OCP' ,,, Le classi sono aperte per estensione, ma chiuse per la modifica .... E come so' I costruttori non possono essere ereditati, e quindi NON POSSONO essere sovrascritti, quindi è Immutabile. ... ' –

+0

Vedere [questo] (https://www.securecoding.cert.org/confluence/display/java/MET05-J.+Ensure+that+constructors+do+not+call+overridable+methods) per una buona spiegazione del motivo per cui non si dovrebbe mai chiamare un metodo sovrascrivibile da un costruttore. La maggior parte degli strumenti lint si lamenterà di chiamare i metodi setter da un costruttore (a meno che il metodo o la classe non sia definitiva, o il metodo sia privato - nel qual caso il metodo non può essere sovrascritto). –

0

secondo quanto già affermato è abbastanza pericoloso per chiamare i metodi Overridable in costruttore. Tuttavia, se hai bisogno di eseguire una sorta di convalida che ha luogo nel setter hai ancora alcuni modi per raggiungerlo.

  1. Effettuare il setter finale. La soluzione più veloce. Questo è già stato affermato ma non è l'unica opzione.
  2. Utilizzare copia privata del setter.
  3. Utilizzare il metodo di fabbrica anziché il costruttore. Di solito mi attengo a questo. Perché in questo modo hai più libertà di gestire la situazione se la convalida fallisce e comunica intento migliore di (2)