2013-10-15 13 views
6

Quindi, ad esempio, diciamo che abbiamo un abstract class chiamato Question, quella domanda contiene un sacco di stringhe, una per la domanda stessa, una per la risposta e due risposte inviate a l'utente, se ha ottenuto la domanda giusta/sbagliata.Best practice per il salvataggio dei dati in classi astratte

public abstract class Question { 

    private final String question; 
    private final String answer; 
    private final String answerCorrect; 
    private final String answerWrong; 

} 

La mia domanda è fondamentalmente, quale sarebbe un modo comune per inizializzare tutte le stringhe? Finora ho inventato 2 versioni su come farlo, hanno i loro aspetti negativi e negativi e volevo sapere se c'era una sorta di "migliore pratica di codifica" per questo.


Versione A
Inizializzare tutto nel costruttore.

public abstract class Question { 

    //... 

    public Question(String question, String answer, String answerCorrect, String answerWrong) { 

     this.question = question; 
     this.answer = answer; 
     this.answerCorrect = answerCorrect; 
     this.answerWrong = answerWrong; 

    } 
} 

Questo sembra abbastanza conveniente, l'unico problema che ho con questo è che gli utenti non saranno sicuri, in cui ordinare le stringhe devono essere.

public class ExampleClass extends Question { 

    public ExampleClass() { 
     super("I think, that's the answer", "and that's the question", "answer wrong?", "answer right?"); 
    } 

} 

Versione B
Non inizializzare immediatamente e attendere che l'utente per farlo.

public abstract class Question { 

    //... 

    public Question() { 

     this.question = ""; 
     this.answer = ""; 
     this.answerCorrect = ""; 
     this.answerWrong = ""; 

    } 

    public void setQuestion(String question) { 
     this.question = question; 
    } 

    //... 
} 

questo rende più facile per inizializzare le variabili, ma le stringhe non può più essere final e non è garantito che l'utente inizializzerà tutti loro.


Ho anche pensato di lasciare il bambino classe implementare metodi astratti che vengono chiamati nel costruttore di Question per inizializzare tutte le stringhe e per tenerli final, ma quella versione sembrava un po 'troppo strano per me .

Ci sono altri/modi migliori per farlo? Quale versione dovrei preferire?
Grazie in anticipo per il vostro supporto.

+0

In questo caso speciale, voterei per la versione A. Perché? Perché vuoi creare immutables. I loro valori non cambieranno dopo la creazione. – Fildor

+2

Il tuo codice non compilazione se i tuoi attributi sono 'final' e si mette un' setter' – nachokk

+3

@nachokk ho parlato: "(...) le stringhe non possono più essere definitiva (...)" –

risposta

1

La versione A è la strada da percorrere. Hai ragione, però, se non dici ai tuoi utenti (gli altri sviluppatori che presumo) quale parametro è, non c'è modo per loro di sapere dove scrivere cosa.

Questo è dove Javadoc è utile.

Ecco un esempio:

/** 
* Create a new instance of Question given the following parameters: 
* 
* @param question This is the question 
* @param answer This is the answer 
* @param answerCorrect Whenever someone guesses correct, print this 
* @param answerWrong Whenever someone guesses wrong, print this 
*/ 
public Question(String question, String answer, String answerCorrect, String answerWrong) { 

    this.question = question; 
    this.answer = answer; 
    this.answerCorrect = answerCorrect; 
    this.answerWrong = answerWrong; 

} 
+0

Questo è dove "nominare i parametri propriamente" torna utile;) – Fildor

+2

Solo dicendo forma propria esperienza: Stato cosa succede se uno dei params è nullo - o in generale, ciò che si aspetta che siano. E aggiungi sempre unità se un param può averne uno. (Come "int time" - che cos'è? Seconds? Days? Può essere negativo?) – Fildor

+0

@Fildor: volevo usare gli stessi nomi di 'felix fritz' nella sua domanda. Il commento vuole essere un'aggiunta alla mia risposta? Se è così: sono d'accordo. Personalmente preferisco nomi come "listCarBrands" o "btnCreateNewEntry" per descrivere un elenco di marchi di automobili e un pulsante che ha lo scopo di creare una nuova voce rispettivamente. In questo modo posso ottenere rapidamente una panoramica di tutti i miei pulsanti, ad esempio, se digito 'btn' e premo Ctrl + Spazio (suggerimenti di completamento automatico) nel mio IDE preferito. – Izmaki

1

Questo potrebbe essere eccessivo, ma credo che si potrebbe usare un costruttore qui ...

public class Question 
{ 
    private final String question; 
    private final String answer; 
    private final String answerCorrect; 
    private final String answerWrong; 

    Question(QuestionBuilder builder) { 
     this.question = builder.question; 
     this.answer = builder.answer; 
     this.answerCorrect = builder.answerCorrect; 
     this.answerWrong = builder.answerWrong; 
    } 

    // public getters omitted to shorten answer 

    @Override 
    public String toString(){ 
     return String.format("question: '%s', answer: '%s', answerCorrect: '%s', answerWrong: '%s'", question, answer, answerCorrect, answerWrong); 
    } 

    public static void main(String[] args) { 
     QuestionBuilder qb = new QuestionBuilder(); 
     qb = qb.question("This is the question").answer("This is the answer").answerCorrect("Correct answer").answerWrong("Wrong Answer"); 
     Question question = new Question(qb); 
     System.out.println(question); 
    } 


    public static class QuestionBuilder{ 
     private String question; 
     private String answer; 
     private String answerCorrect; 
     private String answerWrong; 

     public QuestionBuilder question(String question) { 
      this.question = question; 
      return this; 
     } 

     public QuestionBuilder answer(String answer) { 
      this.answer = answer; 
      return this; 
     } 

     public QuestionBuilder answerCorrect(String answerCorrect) { 
      this.answerCorrect = answerCorrect; 
      return this; 
     } 

     public QuestionBuilder answerWrong(String answerWrong) { 
      this.answerWrong = answerWrong; 
      return this; 
     } 
    } 
} 

Dà l'uscita

question: 'This is the question', answer: 'This is the answer', answerCorrect: 'Correct answer', answerWrong: 'Wrong Answer'

Nota: Realizzo la o la domanda originale era in riferimento a una classe astratta. Ho usato una classe concreta per dare un esempio funzionante, sebbene la soluzione possa essere adattata per l'uso con una classe astratta.

+0

@Dukeling concordato, il costruttore non costringe l'utente a impostare ognuno dei valori, ma questo vale anche per la soluzione 'la versione B' del PO. A differenza della soluzione 'versione B', credo che il Builder dia l'immutabilità che OP desiderava. –

+0

Non ho mai visto qualcosa di simile prima, questo è fantastico! E penso che se lo sviluppatore decidesse di non inizializzare tutto, sarebbe come impostare la stringa su null nella versione A, giusto? Mi piace l'idea. –

+0

@felixfritz Questo è corretto. Se, per esempio, hai chiamato solo '.answer (...) 'metodo, gli elementi rimanenti sarebbero' null' e l'output risultante sarebbe 'domanda: 'Questa è la domanda', risposta: 'null', replyCorrect: 'null', answerWrong: 'null'' L'esempio che ho fornito dovresti compilare ed eseguire in modo che tu possa facilmente giocare con esso in un debugger per vedere come funzionerebbe in diverse situazioni. –

1

Invece di pensare agli attributi (come ad esempio question) come solo variabili, pensate alle restrizioni sui loro valori che devono essere rispettate affinché le classi si comportino correttamente. Possono essere nulli? Possono essere vuoti? Ora progetta i tuoi metodi e il costruttore, quindi è impossibile che tali restrizioni vengano interrotte. Potresti scoprire che il modo solo per è quello di impostare i valori iniziali nel costruttore (la tua versione A). Potrebbe essere necessario aggiungere controlli di pre-condizione ai metodi del costruttore e setter, che controllano i valori dati a favore di un'eccezione appropriata (NullPointerException o IllegalArgumentException) se i valori passati a loro comporterebbero l'interruzione delle restrizioni.

Inoltre, considerare in realtà ha senso modificare il valore di un attributo dopo che l'oggetto è stato creato. In caso contrario, l'attributo non dovrebbe essere un setter, rendendo impossibile la versione B.

+0

Se una variabile non può essere nullo (ed è definitiva), dovrei lanciare immediatamente NullPointerException? –

+0

@felixfritz Sì; Ho modificato la mia risposta per chiarire questo. – Raedwald

+0

Questo approccio rende * impossibile * che gli attributi abbiano valori non validi, oppure che il codice che tenta di avere valori non validi non riesca in modo rapido: http://stackoverflow.com/questions/2807241/what-does-the-expression-fail -Early-media-e-quando-sarebbe-you-want-to-do-so – Raedwald

Problemi correlati