3

Nice day to everybody.

I have an abstract class with the method runRandomExercise(), and several classes that extends it to add different kind of exercise.

I now want to chose a random type exercise, so I need to randomly choose one of the classes, and call runRandomExercise() on that.

For now I am manually coding this, which is not the very best solution I think. However, I can’t store just the classes in the array since the class type is different, and if I use object[] I can’t call the runRandomExercise() method. Any smart way to handle this?

Here is my code till now. It works, but it’s gonna be a pain to add other classes...

/*Specific classes that extend abstract class TrainingClass with the runRandomExercise() method*/
private MatheMagic mMathMag;
private Mnemonics mMnemonics;
private String[] mTrainingClasses;


/*Initialize classes*/
mMathMag = new MatheMagic();
mMnemonics = new Mnemonics();

/*Manually store classe names*/
mTrainingClasses = new String[2];
mTrainingClasses[0] = "mMathMag";
mTrainingClasses[1] = "mMnemonics"; 


/*Return random exercise*/
public String[] RandomExercise() {
    Random aGenerator = new Random();

    /*Get random class name*/
    int rnd = aGenerator.nextInt(mTrainingClasses.length);
    String aChosen = mTrainingClasses[rnd];

    String[] aRes = new String[2];


    if (aChosen == "mMathMag") {
        aRes = mMathMag.runRandomExercise();
    } else if (aChosen == "mMnemonics") {
        aRes = mMnemonics.runRandomExercise();
    }

    return aRes;
}

EDIT Here is how TrainingClass is defined:

/** Common interface for all exercises */ 
public interface Exercise { 
   public String[] run();
}

/** Common interface for all training classes */
 public abstract class TrainingClass {

  private Random mRandGen = new Random();
  public ArrayList<Exercise> mExerciseTypes = new ArrayList<Exercise>();

  /** Run a random exercise */
 public String[] runRandomExercise() {
    int i = mRandGen.nextInt(mExerciseTypes.size());
    return mExerciseTypes.get(i).run();
 }
}



/*Specific training class*/

public class MatheMagic extends TrainingClass {

 public MatheMagic() {

    class SomeExercise implements Exercise {

        public String[] run() {

             String[] mRes = new String[2];
              mRes[0] = "Question type 1";
              mRes[1] = "Answer type 1";
            return mRes;
        }

    }

    class SomeOtherExercise implements Exercise {

        public String[] run() {

             String[] mRes = new String[2];
              mRes[0] = "Question type 2";
              mRes[1] = "Answer type 2";
            return mRes;
        }

    }
    SomeExercise mN = new SomeExercise();

    SomeOtherExercise mS = new SomeOtherExercise();

    mExerciseTypes.add(mN);
    mExerciseTypes.add(mS);
 } 

}
DavidTonarini
  • 941
  • 3
  • 17
  • 35

2 Answers2

4

Easy solution is to create an interface with the common method and have all your classes extend it.

Create a collection or array of that type instead of Object; you can simply iterate through or randomly select and call the method you want.

It feels like a Command pattern from GoF to me.

public interface Exercise {
    void execute();
}

Now your classes do this:

public class MatheMagic implements Execise {
    public void execute() {
        // special logic here.
    }
}

Then you can do this:

int numExercises = 1;
Exercise [] exercises = new Exercise[numExercises];
exercises[0] = new MatheMagic();
for (Exercise exercise : exercises) {
    exercise.execute();
}
duffymo
  • 305,152
  • 44
  • 369
  • 561
  • If I get this correctly, it won’t work on abstract classes, right? This means therefore that I would need to rewrite the runRandomExercise() method in each class, which will get me back to step one. Or is there a turnaround that I am not seeing? – DavidTonarini Sep 03 '12 at 23:54
  • I edited the question to show how the TrainingClass is defined. – DavidTonarini Sep 03 '12 at 23:58
  • Why not? Just make the class you require subclasses to override abstract. Everything else that I said works. Interfaces just mean better mixin behavior; they'll also work for those cases where you want one of your classes to extend something else. – duffymo Sep 04 '12 at 00:10
  • I didn’t understood that I could make a TrainingClass[] array, and the fill it with the subclasses. Thanks! – DavidTonarini Sep 04 '12 at 00:23
1

Yes, yes you can store all those Classes in an array and then call them at random. How? Create an interface and in all your classes derive from that interface. That way you can invoke based on interface, and not on implementation.

alvonellos
  • 1,009
  • 1
  • 9
  • 27