2010-02-05 23 views
9

Escribo un código de demostración para una API que hemos creado y sigo encontrando el mismo problema en el que me repito una y otra vez hasta el cansancio. Estoy muy consciente de que Java tiene programados cierres, pero ahora no tengo acceso a ellos. Esto es lo que se repite por todo el lugar que me gustaría a la caja solo en su propio pequeño rincón:¿Funciones de composición en Java?

public BarObj Foo(Double..._input){ 
    try{ 
     //things that vary per function 
     //but everything else... 
    } catch(NullException _null){ 
     m_Logger.error("Null error exception caught in Blah::Foo"); 

     return null; 
    } catch(Exception ex){ 
     m_Logger.error(ex.getMessage()); 

     return null; 
    } 
} 

Acerca de la única manera que he pensado para ir de evitar esto es haciendo pasar una Method en una función que lleva consigo la lógica try-catch y envolviendo todo en otra función de este modo:

public BarObj MyFunc(Double..._input){ 
    return compose("MyLogic",_input); 
} 

private BarObj MyLogic(Double..._input) 
    throws Exception{ 
    //stuff 
} 

pero se ve feo y lleva consigo una gran cantidad de texto modelo. ¿Hay una manera más fácil de componer funciones en Java?

+0

creo que algunas de las propuestas las extensiones para cierres en java parecen incluso más feas. – DerMike

Respuesta

8

en Java esto es muy difícil ya que no hay soporte de primera clase para las funciones (a diferencia de clojure o scala y probablemente otras).

Sin embargo, puede encapsular la operación en un objeto:

interface Function<R, T> { 

    R call(T... input); 
} 

continuación refactorizar Foo como:

static <R, T> R runFunction(Function<R, T> function, T ... input){ 
    try{ 
     return function.call(input); 
    } catch(NullPointerException _null){ 
     m_Logger.error("Null error exception caught in Blah::Foo"); 
     return null; 
    } catch(Exception ex){ 
     m_Logger.error(ex.getMessage()); 
     return null; 
    } 
} 

caso_prueba:

class SumDoubles implements Function<Double, Double> { 

    @Override 
    public Double call(Double... input) { 
     Double sum = 0.0; 

     for (Double d : input) { 
      sum += d; 
     } 

     return sum; 
    } 
} 

@Test 
public void sum() { 
    Double sum = runFunction(new SumDoubles(), 1.0, 2.0, 3.0); 
    assertThat(sum, is(6.0)); 
} 
+0

¿Sugeriría entonces que estos se hagan como clases privadas dentro de la clase más grande 'Foo'? Creo que es una buena separación de preocupaciones. Por cierto, amo a Scala. – wheaties

2

Probar lambdaj. Permite agregar un poco de FP a Java de una manera bastante ligera y legible. En particular en este closure wiki page puede encontrar un ejemplo muy similar a lo que está tratando de lograr,

0

Esta es obviamente su llamada, pero con la mayoría de las demos de API que he usado, prefiero el formato más largo que tiene en el parte superior. Después de revisar el código, normalmente copio y pego para verificar que la API funciona como creo que lo hace y luego lo modifico desde allí. Cambiar el formato para ocultar algunas de las piezas repetitivas es definitivamente lo que quieres hacer para el desarrollo de OO, pero creo que este código de demostración es algo que los 'dioses del código limpio' entenderían :-).

0

No hay forma de hacerlo en Java, pero intente usar groovy si es posible para usted. La otra opción que puede tener envoltura similar es usar aspecto. ver aspectj.

0

Me enteré de la forma en que esto se hace en Java es crear una interfaz que tiene un método. En tu código, usas clases que implementan esa interfaz.

Cuestiones relacionadas