Можно ли передавать арифметические операторы методу в java?
Сейчас мне нужно написать метод, который выглядит так:
public String Calculate(String operator, double operand1, double operand2)
{
if (operator.equals("+"))
{
return String.valueOf(operand1 + operand2);
}
else if (operator.equals("-"))
{
return String.valueOf(operand1 - operand2);
}
else if (operator.equals("*"))
{
return String.valueOf(operand1 * operand2);
}
else
{
return "error...";
}
}
Было бы неплохо, если бы я мог написать код более как это:
public String Calculate(String Operator, Double Operand1, Double Operand2)
{
return String.valueOf(Operand1 Operator Operand2);
}
Таким образом, оператор заменит арифметические операторы (+, -, *,/...)
Кто-нибудь знает, возможно ли что-то подобное в java?
Ответы
Ответ 1
Нет, вы не можете сделать это на Java. Компилятор должен знать, что делает ваш оператор. Вместо этого вы можете перечислить:
public enum Operator
{
ADDITION("+") {
@Override public double apply(double x1, double x2) {
return x1 + x2;
}
},
SUBTRACTION("-") {
@Override public double apply(double x1, double x2) {
return x1 - x2;
}
};
// You'd include other operators too...
private final String text;
private Operator(String text) {
this.text = text;
}
// Yes, enums *can* have abstract methods. This code compiles...
public abstract double apply(double x1, double x2);
@Override public String toString() {
return text;
}
}
Затем вы можете написать такой метод:
public String calculate(Operator op, double x1, double x2)
{
return String.valueOf(op.apply(x1, x2));
}
И назовите его следующим образом:
String foo = calculate(Operator.ADDITION, 3.5, 2);
// Or just
String bar = String.valueOf(Operator.ADDITION.apply(3.5, 2));
Ответ 2
аргументы метода в Java должны быть выражениями. Сам оператор не является выражением. Это невозможно в Java.
Вы можете, конечно, передать объекты (возможно, enum
константы), которые представляют эти операторы, и действовать соответственно, но вы не можете передавать сами операторы в качестве параметров.
Дополнительные советы
Поскольку вы только начинаете Java, лучше всего направить эту информацию на раннем этапе, чтобы облегчить ваше будущее развитие.
- Имена методов начинаются с строчной буквы:
calculate
вместо calculate
- Переменные имена начинаются с строчной буквы:
operator
вместо operator
-
Double
- ссылочный тип, поле для примитивного типа Double
.
- Эффективное Java 2nd Edition, пункт 49: Предпочитают примитивные типы для примитивов в штучной упаковке.
- Не
return "error..."
. Вместо этого throw new IllegalArgumentException("Invalid operator");
См. также
Ответ 3
Вы не можете передавать операторов напрямую. Вы можете использовать функторы.
public double Calculate(BinaryFunction<Double, Double, Double> op, double Operand1, double Operand2)
{
return (double)op.evaluate(Operand1, Operand2);
}
Ответ 4
Есть только громоздкий способ сделать это с помощью интерфейса обратного вызова. Что-то вроде
interface Operator {
public Double do(Double x, Double y);
}
Затем вы реализуете необходимые вам операторы:
Operator plus = new Operator() {
public Double do(Double x, Double y) {
return x + y;
}
};
И ваш общий метод принимает оператор и два аргумента:
public String Calculate(Operator operator, Double x, Double y) {
return String.valueOf( operator.do(x, y) );
}
Вы также можете использовать перечисление вместо интерфейса, если вам нужно только меньшее, фиксированное число операторов.
Ответ 5
Вы можете либо
-
Используйте функциональный язык для JVM для реализации этой части вашего кода (clojure, scala et el), оберните лямбда-функции вокруг математических операторов и передайте эти функции в качестве параметров
-
Получить оценщик выражений для Java, например http://www.singularsys.com/jep/ (и также должно быть много бесплатных альтернатив)
Ответ 6
Нет, это невозможно сделать.
Вам понадобится парсер для выполнения того, что вы хотите, и это может быть громоздким.
Вероятно, вы задаете неправильный вопрос, так как вы получаете неправильный ответ.
Если вы ищете математический синтаксический анализатор, вы можете взглянуть на этот проект на SF: http://sourceforge.net/projects/jep/
В этом могут быть ответы.
Ответ 7
Было бы хорошо, не так ли? Но вы просто не можете этого сделать. Возможно, вы, возможно, выполните нечто подобное, написав собственные "операторы".
public interface Operator {
Double calculate(Double op1, Double op2);
}
public Addition implements Operator {
@Override
Double calculate(Double op1, Double op2) { return op1 + op2; }
}
public class Calculator {
private static Operator ADDITION = new Addition();
private static Map<String,Operator> OPERATORS = new HashMap<String,Operator>();
static {
OPERATORS.put("+",ADDITION);
}
public String Calculate(String operator, Double operand1, Double operand2) {
return String.valueOf(OPERATORS.get(operator).calculate(operand1,operand2);
}
}
Вы получите представление о том, как распространить это на многие другие операторы... и, разумеется, не только пары. Преимущество моего метода в том, что вы можете фактически сохранить свою подпись метода принятия оператора String.
Ответ 8
Операторы, AFAIK, не могут передаваться как параметр на любом языке (по крайней мере, я сталкивался).
Причина состоит в том, что только значения (либо по копиям, либо по ссылкам) могут передаваться как "значения для параметров".
И операторы не представляют значений.