2010-06-07 4 views
3

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

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

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

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

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

+0

Ваш дизайн кажется немного назад. Разве не было бы смысла создавать экземпляр «SoccerRobot» с конкретной стратегией? –

+0

SoccerRobot представляет физические свойства робота, а не самого приложения. Он обеспечивает высокоуровневое управление роботом (navigateTo, getBallAngle и т. Д.). Поэтому я не думаю, что он должен придерживаться стратегии. – Eric

ответ

7

Перемещение основного метода в отдельный класс. Отдельные проблемы
Стратегия (название говорит все это)
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()) 
    } 
} 
1

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

public class UselessStrategy 

и сделать

Strategy s = new UselessStrategy(); 
+0

Эта первая ошибка была копией и вставкой. И я хотел бы, чтобы основной метод базового класса работал, если бы я должен был вывести другой класс из Стратегии, скажем «Полезная стратегия». Я хотел бы, чтобы основной метод каким-то образом знал, из какого класса он вызван, и создайте экземпляр указанного класса. – Eric

+0

Основной метод базового класса не «работает» для любого производного класса, только для него, как и любой другой статический метод. Но так как люди изобрели параметры командной строки, в вашем случае нет необходимости иметь несколько основных методов. Используйте параметры в качестве ввода для фабрики, чтобы создать свои стратегии. – unbeli

3

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

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

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

+0

'Class.forName' не работает на моей платформе. – Eric

+0

Это более чем обходной путь, для меня это решение. –

+0

'Class.forName' не требуется, существуют другие способы сопоставления ключа, переданного с вектором аргумента, в конкретный класс. –

0

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

+0

Метод 'main' вызывается, когда программа выполняется. Класс 'UselessStrategy' был бы скомпилирован, что бы _hopefully_ вызывать метод' main' в 'Strategy' – Eric

1

Я бы передумал это.

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

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

2

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

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") 
    } 
} 
Смежные вопросы