java que dinamica - Punteros de función en Java




6 Answers

La expresión idiomática de Java para funcionalidad de puntero a función es una clase anónima que implementa una interfaz, por ejemplo

Collections.sort(list, new Comparator<MyClass>(){
    public int compare(MyClass a, MyClass b)
    {
        // compare objects
    }
});

Actualización: lo anterior es necesario en las versiones de Java anteriores a Java 8. Ahora tenemos alternativas mucho mejores, a saber, lambdas:

list.sort((a, b) -> a.isGreaterThan(b));

y referencias de métodos:

list.sort(MyClass::isGreaterThan);
estructura los

Esto puede ser algo común y trivial, pero parece que tengo problemas para encontrar una respuesta concreta. En C # hay un concepto de delegados, que se relaciona fuertemente con la idea de indicadores de función de C ++. ¿Hay una funcionalidad similar en Java? Dado que los indicadores están algo ausentes, ¿cuál es la mejor manera de hacerlo? Y para ser claros, estamos hablando de primera clase aquí.




Puedes usar la reflexión para hacerlo.

Pase como parámetro el objeto y el nombre del método (como una cadena) y luego invoque el método. Por ejemplo:

Object methodCaller(Object theObject, String methodName) {
   return theObject.getClass().getMethod(methodName).invoke(theObject);
   // Catch the exceptions
}

Y luego usarlo como en:

String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");

Por supuesto, verifique todas las excepciones y agregue los moldes necesarios.




Esto trae a la mente la Ejecución en el Reino de los Nombres de Steve Yegge. Básicamente, establece que Java necesita un objeto para cada acción y, por lo tanto, no tiene entidades "solo verbales" como indicadores de función.




No existe tal cosa en Java. Tendrá que ajustar su función en algún objeto y pasar la referencia a ese objeto para pasar la referencia al método en ese objeto.

Sintácticamente, esto se puede aliviar en cierta medida mediante el uso de clases anónimas definidas en el lugar o clases anónimas definidas como variables miembro de la clase.

Ejemplo:

class MyComponent extends JPanel {
    private JButton button;
    public MyComponent() {
        button = new JButton("click me");
        button.addActionListener(buttonAction);
        add(button);
    }

    private ActionListener buttonAction = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // handle the event...
            // note how the handler instance can access 
            // members of the surrounding class
            button.setText("you clicked me");
        }
    }
}



Implementé el soporte de devolución de llamada / delegado en Java utilizando la reflexión. Los detalles y la fuente de trabajo están disponibles en mi sitio web .

Cómo funciona

Tenemos una clase principal llamada Callback con una clase anidada llamada WithParms. La API que necesita la devolución de llamada tomará un objeto Callback como parámetro y, si es necesario, creará una Callback.WithParms como variable de método. Como gran parte de las aplicaciones de este objeto serán recursivas, esto funciona de manera muy limpia.

Dado que el rendimiento sigue siendo una gran prioridad para mí, no quería que se me pidiera crear una matriz de objetos desechables para guardar los parámetros para cada invocación; después de todo, en una gran estructura de datos podría haber miles de elementos, y en un procesamiento de mensajes Es posible que terminemos procesando miles de estructuras de datos por segundo.

Para que sea seguro en cuanto a los hilos, la matriz de parámetros debe existir de forma exclusiva para cada invocación del método de la API, y para la eficacia debe usarse la misma para cada invocación de la devolución de llamada; Necesitaba un segundo objeto que sería barato de crear para vincular la devolución de llamada con una matriz de parámetros para la invocación. Pero, en algunos escenarios, el invocador ya tendría una matriz de parámetros por otros motivos. Por estos dos motivos, la matriz de parámetros no pertenecía al objeto Callback. Además, la opción de invocación (que pasa los parámetros como una matriz o como objetos individuales) pertenece a la API mediante la devolución de llamada, lo que le permite usar la invocación que mejor se adapte a su funcionamiento interno.

La clase anidada WithParms, entonces, es opcional y tiene dos propósitos, contiene la matriz de objetos de parámetro necesaria para las invocaciones de devolución de llamada, y proporciona 10 métodos invoke () sobrecargados (con de 1 a 10 parámetros) que cargan la matriz de parámetros y luego invocar el objetivo de devolución de llamada.




En relación con la mayoría de las personas aquí, soy nuevo en Java, pero como no he visto una sugerencia similar, tengo otra alternativa que sugerir. No estoy seguro de si es una buena práctica o no, o incluso se sugirió antes y simplemente no lo entendí. Me gusta, ya que creo que es auto descriptivo.

 /*Just to merge functions in a common name*/
 public class CustomFunction{ 
 public CustomFunction(){}
 }

 /*Actual functions*/
 public class Function1 extends CustomFunction{
 public Function1(){}
 public void execute(){...something here...}
 }

 public class Function2 extends CustomFunction{
 public Function2(){}
 public void execute(){...something here...}
 }

 .....
 /*in Main class*/
 CustomFunction functionpointer = null;

luego, dependiendo de la aplicación, asignar

 functionpointer = new Function1();
 functionpointer = new Function2();

etc.

y llamar por

 functionpointer.execute();



Related