سؤال

I have two classes lets say "QuestionOne" and "QuestionsTwo" which are very similar and inherit from a Baseclass "Question". Now I want to write a method which fills a ArrayList with Objects of either class.

public ArrayList<QuestionOne> list = new ArrayList<QuestionOne>();

public void fill(QuestionOne questionOne){
list.add(questionOne);
}

That would be a method to fill QuestionOne objects. But I want the method to be able to fill the list with both type of objects "QuestionOne" and "QuestionTwo".

What I would like to add...I want to use alle methods of "questionOne" and "questionTwo".

How can I achieve this? Do I need an Interface? I don't know...

هل كانت مفيدة؟

المحلول 4

As mentioned, you can create an ArrayList of type Question. This means that you will only be able to use methods that are defined in the Question class.

For example

public class Question {

    public void askAQuestion(){
        System.out.println("Im asking a question");
    }

}

_

public class QuestionOne extends Question {

    @Override
    public void askAQuestion(){
        // You can override a method. As long as it has the same name and
        // return type, it can have it's own functionality
        System.out.println("Im asking question one");
    }

    public void doSomethingElse(){
        // Because this method is not in the Question class, you cannot use
        // it in your ArrayList
    }

}

_

public class QuestionTwo {

    @Override
    public void askAQuestion(){
        System.out.println("Im asking question two");
    }

}

_

public class MainClass {

    public static void main (String[] args){

        List<Question> questions = new ArrayList<Question>();
        questions.add(new QuestionOne());
        questions.add(new QuestionTwo());

        questions.get(0).askAQuestion(); // Outputs "Im asking question one"
        questions.get(1).askAQuestion(); // Outputs "Im asking question two"
    }

}

نصائح أخرى

Make an ArrayList<Question> and fill it up that way. Although you'll only have the interface available, that the Question class exposes.

If you use an abstract class Question, you will be able to use an arraylist of Question to store both subclass objects.

class Question{}
class QuestionOne extends Question{}
class QuestionTwo extends Question{}

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

// This method will take any subclass of Question.
public void fill(Question question){
  list.add(question);
}

To backcast, you can use instanceof to compare:

{ //...
  for(final Question element:list){
    if(element instanceof QuestionOne){
      QuestionOne question=(QuestionOne)element;
      // Use it here.
    }
    //...
  }
}
public ArrayList<Question> list = new ArrayList<Question>();

Now list.add(x) will work whenever x is a Question or any object of a subclass of Question.

In general, any time you say that a variable or parameter has type C, it can contain a reference to a C or any subclass of C. This applies just as well to the parameter of the ArrayList add routine, which will look like this:

boolean add(Question e) 

So you can add anything that is a subclass of Question to your list.

P.S.: Some comments are suggesting changing the parameter of fill also. You can do that, but you don't have to. It depends on your requirements. This will still work:

public void fill(QuestionOne questionOne){
    list.add(questionOne);
}

since questionOne is a Question (as well as being a QuestionOne). If you really need to, you could overload fill:

public void fill(QuestionOne questionOne){
    System.out.println("I'm adding a Type I question");
    list.add(questionOne);
}

public void fill(QuestionTwo questionTwo){
    if (questionTwo.isInteresting()) {
        // assume isInteresting is a method that is defined only for QuestionTwo
        System.out.println("I'm adding a Type II question");
        list.add(questionTwo);
    }
}

Usually it would be better to do something like this by adding a polymorphic method to Question that is overridden in QuestionOne and QuestionTwo. But this isn't always possible. I'm just bringing this up to point out that the parameter of fill doesn't actually need to change, although you might want to.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top