2010-02-05 16 views
9

Sto scrivendo codice demo per un'API che abbiamo creato e continuo a incontrare lo stesso problema in cui mi sto ripetendo, più e più volte fino alla nausea. Sono dolorosamente consapevole del fatto che a Java è stato programmato di aggiungere delle chiusure ma ora non ho accesso ad esse. Ecco cosa si ripete in tutto il posto che mi piacerebbe box solo in essa la propria piccolo angolo:Composizione di funzioni in 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; 
    } 
} 

Circa l'unico modo che ho pensato di andare in giro questo è di passare una Method in una funzione che porta con sé la logica try-catch e avvolgendo tutto in un'altra funzione in questo modo:

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

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

ma sembra brutto e porta con sé un sacco di testo standard. C'è un modo più semplice per comporre le funzioni in Java?

+0

penso che alcune delle proposte le estensioni per chiusure in java sembrano ancora più brutte. – DerMike

risposta

8

in Java questo è molto difficile poiché non esiste un supporto di prima classe per le funzioni (a differenza di clojure o scala e probabilmente altro).

Tuttavia, è possibile incapsulare l'operazione in un oggetto:

interface Function<R, T> { 

    R call(T... input); 
} 

quindi refactoring Foo come:

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

TestCase:

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

Suggeriresti quindi che siano fatti come classi private all'interno della più grande classe 'Foo'? Penso che sia una bella separazione di preoccupazioni. A proposito, io amo Scala. – wheaties

2

Prova lambdaj. Permette di aggiungere un po 'di FP a java in un modo abbastanza leggero e leggibile. In particolare in questo closure wiki page puoi trovare un esempio molto simile a quello che stai cercando di raggiungere,

0

Questa è ovviamente la tua chiamata, ma con la maggior parte delle demo API che ho usato preferisco il formato più lungo che hai al superiore. Dopo aver esaminato il codice, di solito faccio copia e incolla per verificare che l'API funzioni come penso che lo faccia, quindi la modifica da lì. Cambiare il formato per nascondere alcuni dei pezzi ripetitivi è sicuramente ciò che si vuole fare per lo sviluppo OO, ma penso che questo tipo di codice demo sia qualcosa che gli "dei codici puliti" avrebbero compreso :-).

0

Non c'è modo di farlo in java, ma prova ad usare groovy se è possibile per te. L'altra opzione che puoi avere come wrapping è l'aspetto. vedi aspectj.

0

Ho imparato il modo in cui questo è fatto in Java è quello di creare un'interfaccia che ha un metodo. Nel tuo codice usi le classi che implementano quell'interfaccia.

Problemi correlati