Is it good practice to add a dummy method to the superclass so that the subclass can override it?

I have a problem. It has to do with calling a subclass method from the superclass, but with a twist. Any insight would be appreciated.

For example, let's say I have a subclass MultipleChoice

that extends an abstract superclass Question

. The class MultipleChoice

has a method addChoice(String choice)

, and Question

it does everything that any question should do, for example, display the question hint and check the correct answer.

I would like to create an instance MultipleChoice

that references Question

and then calls a method addChoice(String choice)

. The reason for this is that I would like to create a list of questions and then ask different types of questions (e.g. multiple choice, true and false, etc.).

Something like that:

ArrayList<Question> list = new ArrayList();
list.add(new MultipleChoice()); //this is valid
list.get(0).addChoice("abc");
list.get(0).addChoice("xyz"); //etc

      

However, this is of course a compile-time error, as not every question is a multiple choice question.

I know two solutions for this.

  • Typecast: ((MultipleChoice)list.get(0)).addChoice("abc");

  • Add the method addChoice(String choice)

    to your superclass Question

    so you can override it MultiplceChoice

    .

As I am going to refer to many times list

, option 1 is good ... ugly, and option 2 just seems like very bad practice, especially as it Question

is abstract.

How can I approach this elegantly?

+3


source to share


2 answers


It is not recommended to add a dummy method to a superclass that will only be used by one subclass. It will lead to confusion and misunderstanding if someone else (or you in the future) works on the code and adds a new question type that your superclass inherits Question

.

You can add objects to your list like this:

ArrayList<Question> list = new ArrayList<Question>();

MultipleChoice multipleChoiceQ1 = new MultipleChoice();
multipleChoiceQ1.addChoice("abc");

MultipleChoice multipleChoiceQ2 = new MultipleChoice();
multipleChoiceQ2.addChoice("xyz");

list.add(multipleChoiceQ1);
list.add(multipleChoiceQ2);

      

With this method, you can add other objects to the list of subclasses Question

, for example:



TrueAndFalse trueAndFalse1 = new TrueAndFalse();
//do something here

TrueAndFalse trueAndFalse2 = new TrueAndFalse();
//do something here

list.add(trueAndFalse1);
list.add(trueAndFalse2);

      

Then, when accessing the list, use instanceof

to check the data type. For example:

for (Question question : list) {
    if (question instanceof MultipleChoice) {
        MultipleChoice multipleChoice = (MultipleChoice) question;
        multipleChoice.doSomething();

    } else if (question instanceof TrueAndFalse) {
        TrueAndFalse trueAndFalse = (TrueAndFalse) question;
        trueAndFalse.doSomethingElse();

    }
}

      

+2


source


There is nothing wrong with your second solution. Assuming Java 1.5 or higher, I would use generics. For example:

public abstract class Question<T>
{
  public void addChoice(T newChoice);
}

public class MultipleChoice extends Question<String>
{
  @Override
  public void addChoice(String newChoice)
  {
    // Do whatever you want here
  }
}

      

You can use Boolean

for right / false questions.

As Keel suggested, you could just add all the options to the question before adding the question to the list. Do you think you are possibly using a constructor where you supply all the items from the front?



Typecasting in the sense you suggest for your first solution can end up leading to runtime errors if you try to do something wrong. Let's say you have the following list of Question objects, by type:

MultipleChoice
MultipleChoice
Boolean
MultipleChoice
Question

      

When you iterate over this list, you know that you have a list of Question objects. You should check the type of each question before trying to use it (using instanceof), or somehow keep track of which element in the list is of type. Think about what will happen if you try to follow through (MultipleChoice)list.get(2)

.

+2


source







All Articles