views:

94

answers:

5

I want to define a base class that defines a main method that instantiates the class, and runs a method. There are a couple of problems though. Here is the base class:

public abstract class Strategy
{
    abstract void execute(SoccerRobot robot);

    public static void main(String args)
    {
        Strategy s = new /*Not sure what to put here*/();
        s.execute(new SoccerRobot())
    }
}

And here is an example derived class:

public class UselessStrategy
{
    void execute(SoccerRobot robot)
    {
        System.out.println("I'm useless")
    }
}

It defines a simple execute method, which should be called in a main method upon usage as a the main application. However, in order to do so, I need to instantiate the derived class from within the base class's main method. Which doesn't seem to be possible.

I'd rather not have to repeat the main method for every derived class, as it feels somewhat unnessary.

Is there a right way of doing this?

+1  A: 

You cannot instantiate an abstract class, but you definitely can instantiate a derived class from the base class. So just remove abstract from class definition

public class UselessStrategy

and do

Strategy s = new UselessStrategy();
unbeli
That first mistake was a copy-and-paste-o. And I'd like the base class' main method to work if I were to derive another class from Strategy, say `Useful Strategy`. I'd like the main method to somehow know which class it is being called from, and instantiate said class.
Eric
Base class' main method does not "work" for any derived class, only for itself, as any other static method. But since people have invented command line parameters, there is no real need to have multiple main methods in your case. Use the parameters as an input for the factory to create your strategies.
unbeli
+6  A: 

Move the main method out into a separate class. Separate concerns
Strategy (the name says it all)
Launcher (assembling components together and triggering execution)

public class Launcher
{
    public static void main(String args)
    {
       Strategy s = new UselessStrategy();
          //OR Strategy s = CreateInstance(args[0]) ;
          //OR equiv mechanism for Dependency Injection if you don't want to hardcode the derived strategy to use.
        s.execute(new SoccerRobot())
    }
}
Gishu
+1  A: 

Static methods, such as "main", are not inherited but can be called directly. As a workaround, you could parameterize the class name as an argument to the main method:

public static void main(String args) throws Exception
{
  String className = (args.length > 0) ? args[0] : 'UselessStrategy';
  Strategy s = (Strategy) Class.forName(className).newInstance();
  s.execute(new SoccerRobot())
}

If Class.forName is not possible, then maintaining a mapping of class names can provide a lookup table, per Andreas_D's comment:

private static Map<String, Class<? extends Strategy>> STRATEGY_NAME =
    new HashMap<String, Class<? extends Strategy>>();

static {
    STRATEGY_NAME.put("Useless", UselessStrategy.class);
    STRATEGY_NAME.put("Better", BetterStrategy.class);
}

public static void main(String args[]) throws Exception {
    String className = (args.length > 0) ? args[0] : null;
    Class<? extends Strategy> klass = STRATEGY_NAME.get(className);
    if (klass == null) klass = UselessStrategy.class;
    Strategy s = klass.newInstance();
    s.execute();
}

Automated methods for maintaining the mapping could be devised, such as using reflection, if the need arises.

maerics
`Class.forName` is a no-go on my platform.
Eric
This is more than a workaround, to me it's THE solution.
Andreas_D
`Class.forName` is not necessary, there are other ways to map a key passed with the argument vector to a concrete class.
Andreas_D
Well that sucks. `newInstance` isn't a supported operation on `Class<T>`...
Eric
Is this some special Java flavor like J2ME, or android? Or is there a restrictive SecurityManager?
maerics
Some special java flavour. [LeJOS NXJ](http://lejos.sourceforge.net/), to be precise.
Eric
Hmm, you should put that name in the question and maybe a tag; it seems to be a specialized Java implementation.
maerics
A: 

Where is the main method called from? If it takes arguments then you can decide a concrete strategy based on those arguments, instantiate that strategy class and call the execute method on it.

abhin4v
The `main` method is called when the program is executed. The `UselessStrategy` class would be compiled, which would _hopefully_ call the `main` method in `Strategy`
Eric
A: 

I'd rethink this.

Put the code that you'd like executed somewhere else, preferably a non-static method, and call that. main() shouldn't be used this way.

I'd recommend creating a separate Strategy class in lieu of main.

duffymo