Могу ли я сопоставить строку с методом в Java? - PullRequest
4 голосов
/ 17 июля 2011

Я пишу оценщик выражений на Java. Я хотел бы иметь возможность добавлять больше операторов (в настоящее время у меня есть только (,), +, -, *, / и ^). В настоящее время мой код выглядит так:

case '+':  
return a+b;  
case '-':  
return a-b;  
case '*':  
return a*b;  
...

Это работает для моего кода, потому что у меня есть только несколько операторов. Однако, если бы я добавил больше операторов, код стал бы загроможденным. Я ищу способ сопоставить оператор (представленный строкой) с методом. Например, «ln» будет сопоставлен с Math.log (), «^» будет сопоставлен с Math.pow () и т. Д.

Как бы я поступил так? Если это невозможно, какие есть альтернативы?

Ответы [ 4 ]

6 голосов
/ 17 июля 2011

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

public interface Operation {
  int apply(int... operands);
}

public abstract class BinaryOperation implements Operation {
  @Override
  public int apply(int... operands) {
    return apply(operands[0], operands[1]);
  }

  abstract int apply(int a, int b);
}

Map<String, Operation> operations = new HashMap<String, Operation>() {{
  put("+", new Operation() {
    @Override
    public int apply(int... operands) {
      return operands[0] + operands[1];
    }
  });
  put("-", new BinaryOperation() {
    @Override
    public int apply(int a, int b) {
      return a - b;
    }
  });
}};
4 голосов
/ 17 июля 2011

Вы можете использовать методы шаблона.

public enum Functions {
    ADD() {
        @Override public int execute(int a, int b) {
            return a+b;
        }
    },
    SUB() {
        @Override public int execute(int a, int b) {
            return a-b;
        }
    };

   //Template method
   public abstract int execute(int a, int b);
}

Затем отобразить строку и перечисление с помощью Map<String, Functions> functionMap Так что если вы хотите добавить, вы можете сделать functionMap.put("+", Functions.ADD); Затем вызвать functionMap.get("+").execute(a,b);

Полагаю, вы также можете использовать varargs, если разные функции принимают разное количество аргументов.public abstract int execute (Integer... inputs);

Этот пример изменен с Максимум использования Java 5.0: трюки Enum и то, что сказал @duffymo.

1 голос
/ 17 июля 2011

Основываясь на предложении Operation, приведенном выше, Map<String, Operation> справился бы с поиском.

0 голосов
/ 17 июля 2011

Я думаю, что ваша установка является оптимальной, поскольку я не могу придумать, как легко сделать это в Java, хотя в языке, подобном c / c ++, вы могли бы легко отображать строки в указатели на функции, но я не думаю, что есть эквивалент об этом в Java AFAIK. Однако красота операторов switch заключается в том, что они фактически избегают беспорядка, потому что визуально вы можете легко увидеть, что такое оператор switch, и просто найти подходящий вам случай (хотя для строк, которые вы создали, нужен гигантский каскад if = = оператор не перегружен в Java для сравнения строк).

Редактировать: см. Комментарий Райана Стюартса, они используют ООП способы делать именно то, что вы хотите. Хотя в некоторых случаях это выглядит более загроможденным, чем ваш оператор switch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...