Наследование основного метода - PullRequest
3 голосов
/ 07 июня 2010

Я хочу определить базовый класс, который определяет метод main, который создает экземпляр класса и запускает метод. Хотя есть пара проблем. Вот базовый класс:

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())
    }
}

А вот пример производного класса:

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

Он определяет простой метод execute, который должен вызываться в main-методе при использовании в качестве основного приложения. Однако для этого мне нужно создать экземпляр производного класса из основного метода основного класса. Что не представляется возможным.

Я бы предпочел не повторять метод main для каждого производного класса, так как он выглядит несколько неестественно.

Есть ли правильный способ сделать это?

Ответы [ 6 ]

7 голосов
/ 07 июня 2010

Переместите метод main в отдельный класс.Отдельные проблемы
Стратегия (название говорит само за себя)
Launcher (сборка компонентов и запуск выполнения)

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())
    }
}
3 голосов
/ 07 июня 2010

Статические методы, такие как "main", не наследуются, но могут вызываться напрямую. В качестве обходного пути вы можете параметризовать имя класса в качестве аргумента основного метода:

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())
}

Если Class.forName невозможно, то поддержание отображения имен классов может обеспечить таблицу поиска, согласно комментарию Andreas_D:

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();
}

Могут быть разработаны автоматизированные методы для поддержки отображения, такие как использование отражения, если возникнет такая необходимость.

2 голосов
/ 05 сентября 2014

Вы можете определить класс в статическом блоке в подклассе.

public abstract class Strategy
{
    protected static Class<? extends Strategy> instanceClass;

    abstract void execute(SoccerRobot robot);

    public static void main(String args)
    {
        Strategy s = instanceClass.newInstance()
        s.execute(new SoccerRobot())
    }
}

и затем

public class UselessStrategy extends Strategy
{
    static {
        instanceClass = UselessStrategy.class;
    }

    void execute(SoccerRobot robot)
    {
        System.out.println("I'm useless")
    }
}
1 голос
/ 07 июня 2010

Я бы переосмыслил это.

Поместите код, который вы хотите выполнить, где-нибудь еще, предпочтительно нестатический метод, и вызовите его.main() не следует использовать таким образом.

Я бы рекомендовал создать отдельный класс Strategy вместо main.

1 голос
/ 07 июня 2010

Вы не можете создать экземпляр абстрактного класса, но вы определенно можете создать экземпляр производного класса из базового класса. Так что просто удалите реферат из определения класса

public class UselessStrategy

и сделать

Strategy s = new UselessStrategy();
0 голосов
/ 07 июня 2010

Откуда вызывается основной метод? Если он принимает аргументы, то вы можете выбрать конкретную стратегию на основе этих аргументов, создать экземпляр этого класса стратегии и вызвать для него метод execute.

...