Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for saving data in abstract classes

So, just as an example, let's say we have an abstract class called Question, that question contains a lot of strings, one for the question itself, one for the answer and two responses posted to the user, if he got the question right / wrong.

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 a common way to initialize all of the strings? So far I've made up 2 versions on how to do it, they have their up- and downsides and I wanted to know, if there was 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 have with this is that users will not be sure, in which order the strings have to be.

public class ExampleClass extends Question {

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

}

Version B
Don't initialize instantly and wait for the user to do it.

public abstract class Question {

    //...

    public Question() {

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

    }

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

    //...
}

This makes it easier to initialize variables, but the Strings can't be final anymore and it's not guaranteed that the user will initialize all of them.


I've also thought about letting the child-class implement abstract methods that are called in the constructor of Question to initialize all the strings and to keep them final, but that version seemed a little too strange to me.

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

like image 632
felix fritz Avatar asked Oct 15 '13 15:10

felix fritz


2 Answers

Version A is the way to go. You're right, though, if you do not tell your users (the other developers I'm assuming) which parameter is which, there is no way for them to know where to type what.

This is where Javadoc comes in handy.

Here's 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;

}
like image 146
Birb Avatar answered Oct 12 '22 04:10

Birb


This might be overkill, but I believe 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 the output

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

Note: I realize the original question was in reference to an abstract class. I used a concrete class so I could give a working example, although the solution can be adapted for use with an abstract class.

like image 26
Jason Braucht Avatar answered Oct 12 '22 05:10

Jason Braucht