È ansible passare operatori aritmetici ad un metodo in java?

In questo momento ho intenzione di scrivere un metodo che assomiglia a questo:

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..."; } } 

Sarebbe bello se potessi scrivere il codice più in questo modo:

 public String Calculate(String Operator, Double Operand1, Double Operand2) { return String.valueOf(Operand1 Operator Operand2); } 

Quindi Operator sostituirà gli operatori aritmetici (+, -, *, / …)

Qualcuno sa se qualcosa di simile è ansible in Java?

No, non puoi farlo in Java. Il compilatore deve sapere cosa sta facendo il tuo operatore. Quello che potresti fare invece è un enume:

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

Puoi quindi scrivere un metodo come questo:

 public String calculate(Operator op, double x1, double x2) { return String.valueOf(op.apply(x1, x2)); } 

E chiamalo così:

 String foo = calculate(Operator.ADDITION, 3.5, 2); // Or just String bar = String.valueOf(Operator.ADDITION.apply(3.5, 2)); 

Gli argomenti del metodo in Java devono essere espressioni. Un operatore di per sé non è un’espressione. Questo non è ansible in Java.

È ansible, naturalmente, passare oggetti (forse costanti enum ) che rappresentano quegli operatori e agire di conseguenza, ma non è ansible passare gli operatori stessi come parametri.


Ulteriori suggerimenti

Dato che stai appena iniziando con Java, è meglio inserire queste informazioni in anticipo per facilitare il tuo sviluppo futuro.

  • I nomi dei metodi iniziano con lettere minuscole: calculate invece di Calculate
  • I nomi delle variabili iniziano con lettere minuscole: operator invece di Operator
  • Double è un tipo di riferimento, la casella per il tipo primitivo double .
    • Efficace Java 2nd Edition, Articolo 49: Preferisci i tipi primitivi ai primitivi in ​​scatola
  • Non return "error..." . Invece, throw new IllegalArgumentException("Invalid operator");

Guarda anche

  • Guida alla lingua Java / Autoboxing
  • Lezioni / eccezioni Java
  • Convenzioni di codifica / Denominazione
    • Errore di sfortuna in questo documento: in che modo questa affermazione ha senso? (Convenzione di denominazione di Sun per le variabili Java)

Non è ansible passare direttamente gli operatori. Potresti usare i funtori .

 public double Calculate(BinaryFunction op, double Operand1, double Operand2) { return (double)op.evaluate(Operand1, Operand2); } 

C’è solo il modo ingombrante di farlo con un’interfaccia di callback. Qualcosa di simile a

 interface Operator { public Double do(Double x, Double y); } 

Quindi implementa gli operatori di cui hai bisogno:

 Operator plus = new Operator() { public Double do(Double x, Double y) { return x + y; } }; 

E il tuo metodo generico accetta un operatore e i due argomenti:

 public String Calculate(Operator operator, Double x, Double y) { return String.valueOf( operator.do(x, y) ); } 

Puoi anche usare un enum invece di un’interfaccia se hai solo bisogno di un numero fisso di operatori più piccolo.

Puoi o

  1. Usa un linguaggio funzionale per JVM per implementare questa parte del tuo codice (clojure, scala et el), avvolgere le funzioni lambda attorno agli operatori matematici e passare quelle funzioni come parametri

  2. Ottieni un valutatore di espressioni per Java come http://www.singularsys.com/jep/ (e ci devono essere anche molte alternative gratuite)

No, non è ansible in questo modo.

Avrai bisogno di un parser per fare ciò che vuoi, e questo può essere ingombrante.

Probabilmente stai facendo la domanda sbagliata, dal momento che stai ricevendo la risposta sbagliata.

Se stai cercando un parser matematico potresti dare un’occhiata a questo progetto su SF: http://sourceforge.net/projects/jep/

Ci potrebbero essere delle risposte in questo.

Sarebbe bello, non sarebbe? Ma non puoi farlo. Probabilmente puoi realizzare qualcosa di simile scrivendo i tuoi “operatori”.

 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 OPERATORS = new HashMap(); static { OPERATORS.put("+",ADDITION); } public String Calculate(String operator, Double operand1, Double operand2) { return String.valueOf(OPERATORS.get(operator).calculate(operand1,operand2); } } 

Ottieni l’immagine di estenderla a molti altri operatori … e ovviamente non solo al doppio. Il vantaggio del mio metodo è che puoi effettivamente mantenere la firma del tuo metodo di accettazione di un operatore String .

Gli operatori, AFAIK, non possono essere passati come parametro in nessuna lingua (almeno quello che ho trovato).

Il motivo è che solo i valori (per copia o per riferimento) possono essere passati come “valori ai parametri”.

E gli operatori non rappresentano valori.