Quiero saber si es posible devolver un operador como si fuera un objeto o un tipo.

Esto sería para analizar una matriz 2D de coordenadas para determinar el cuadro delimitador donde se superponen dos polígonos. La salida de la función determinaría la declaración booleana de los bucles for para que el algoritmo pueda comenzar su análisis desde la parte posterior del polígono en función de la dirección del movimiento del polígono.

public <operator> function(int value){
    if(value < 0) {
        return >=;
    }
    return <=;
}

La sintaxis anterior es obviamente completamente incorrecta, pero estaba buscando de manera óptima algo similar.

Me gustaría usar la función de manera similar a esto:

if(var1 function(value) var2)

¿Existe algo como esto? Si no, ¿hay alguna otra forma de cambiar entre> = y <=?

1
Macklin Entricken 11 may. 2019 a las 02:01

3 respuestas

La mejor respuesta

Puede devolver un BiPredicate:

public BiPredicate<Integer, Integer> function(int value) {
    if(value < 0) {
        return (a, b) -> a >= b;
    }
    return (a, b) -> a <= b;
}
1
shmosel 10 may. 2019 a las 23:16

Lamentablemente no, no puede devolver un operador. De acuerdo con el JLS en lo que respecta a:

return Expression opt ;

La expresión debe denotar una variable o valor de algún tipo T, o se produce un error en tiempo de compilación.

Como un operador no es una variable o un valor, no puede devolverlo.

¿Por qué no hacer que el método haga la comparación?

public boolean function(int value, int num1, int num2){
    if(value < 0) {
        return num1 >= num2;
    }
    return num1 <= num2;
}

Y luego llámalo como:

if(function(value, var1, var2))
2
GBlodgett 10 may. 2019 a las 23:10

Puede usar las interfaces funcionales de Java 8.

Como desea 2 operandos y un resultado booleano, simplemente puede usar BiPredicate, pero dado que desea que los 2 operandos sean del mismo tipo, eso requeriría que repita el tipo, por lo que podría crear una nueva interfaz funcional, por ejemplo llamado BinaryPredicate:

interface BinaryPredicate<T> extends BiPredicate<T, T> {
    // nothing to add
}

Entonces su método podría ser, p. así, si quisieras que los operandos fueran un tipo que implementa Comparable:

public static <T extends Comparable<T>> BinaryPredicate<T> objectOperator(int value){
    if (value < 0)
        return (a, b) -> a.compareTo(b) >= 0;
    return (a, b) -> a.compareTo(b) <= 0;
}

Si desea que los operandos sean valores int, puede crear esto en su lugar:

interface IntBinaryPredicate {
    boolean test(int a, int b);
}

Entonces haz tu método así:

public static IntBinaryPredicate intOperator(int value){
    if (value < 0)
        return (a, b) -> a >= b;
    return (a, b) -> a <= b;
}

Así es como las usarías:

BinaryPredicate<String> stringOp = objectOperator(1);
if (stringOp.test("Foo", "Bar"))
IntBinaryPredicate intOp = intOperator(1);
if (intOp.test(13, 42))
1
Andreas 10 may. 2019 a las 23:27