Best practice for storing data in abstract classes

So, as an example, suppose we have an abstract class called Question , this question contains many lines, one for the question itself, one for the answer and two answers sent to the user if he asked the question correctly / incorrectly.

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

My question basically is what would be the usual way to initialize all the lines? So far I have compiled 2 versions of how to do this, they have their own weaknesses and weaknesses, and I would like to know if there is some kind of “best coding practice” for this.


Version A
Initialize everything in the constructor.

 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; } } 

This seems pretty convenient, the only problem I am facing is that users will not be sure in which order the lines should be.

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

Version B
Do not initialize immediately and wait for the user to do this.

 public abstract class Question { //... public Question() { this.question = ""; this.answer = ""; this.answerCorrect = ""; this.answerWrong = ""; } public void setQuestion(String question) { this.question = question; } //... } 

This simplifies the initialization of variables, but strings cannot be final anymore, and this does not guarantee that the user will initialize all of them.


I also thought about letting the child class implement the abstract methods that are called in the Question constructor to initialize all the lines and keep them final , but this version seemed too strange to me.

Are there any other / better ways to do this? Which version should I prefer?
Thanks in advance for your support.

+6
source share
3 answers

Version A is the way to go. You are right, although if you do not tell your users (other developers whom I assume) what parameter is, then there is no way to find out where to enter them.

This is where Javadoc comes in handy.

Here is an example:

 /** * 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; } 
+1
source

This may be redundant, but I believe that you could use a builder here ...

 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; } } } 

Gives way out

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

Note: I understand that the original question was about an abstract class. I used a specific class, so I could give a working example, although the solution can be adapted for use with an abstract class.

+1
source

Instead of thinking of attributes (like question ) as just variables, think of constraints on their values ​​that must be met for the classes to behave properly. Can they be empty? Can they be empty? Now create your own methods and constructor so that these restrictions cannot be violated. You may find that the only way to do this is to set the initial values ​​in the constructor (your version A). You may need to add precondition checks to your setter constructors and methods that check the values ​​specified by the throwing of a suitable exception ( NullPointerException or IllegalArgumentException ) if the values ​​passed to them violate the restrictions.

Also consider whether it really makes sense to change the attribute value after creating the object. If not, then the attribute should not be a setter, which makes version B impossible.

+1
source

Source: https://habr.com/ru/post/955995/


All Articles