2010-02-05 10 views
9

Ich schreibe Demo-Code für eine API, die wir erstellt haben, und ich stoße immer wieder auf das gleiche Problem, wo ich mich immer und immer wieder wiederhole. Ich bin mir schmerzlich bewusst, dass Java Schließungen hinzugefügt werden soll, aber ich habe jetzt keinen Zugriff darauf. Hier ist, was alle über den Ort wiederholt, dass Ich mag würde nur in seine eigene kleine Ecke Box:Funktionen in Java zusammensetzen?

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

über die einzige Art, wie ich gedacht habe, um diesen zu gehen, ist durch ein Method in eine Funktion übergeben das birgt die try-catch-Logik und sie alle auf in einer anderen Funktion Einwickeln in etwa so:

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

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

aber es sieht hässlich aus und trägt mit ihm eine Menge vorformulierten. Gibt es eine einfachere Möglichkeit, Funktionen in Java zu erstellen?

+0

ich einige der vorgeschlagenen denken Erweiterungen für Verschlüsse in Java sehen noch hässlicher aus. – DerMike

Antwort

8

in Java ist dies sehr schwierig, da es keine erstklassige Unterstützung für Funktionen gibt (im Gegensatz zu Clojure oder Scala und wahrscheinlich anderen).

Sie können jedoch in einem Objekt die Operation kapseln:

interface Function<R, T> { 

    R call(T... input); 
} 

dann Foo Refactoring als:

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

Testfall:

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

Würdest du dann vorschlagen, dass diese als private Klassen innerhalb der größeren 'Foo' Klasse gemacht werden? Ich denke, das ist eine ziemlich schöne Trennung von Sorgen. Übrigens, ich liebe Scala. – wheaties

2

Versuchen Sie lambdaj. Es erlaubt, ein bisschen FP zu Java auf eine ziemlich leichte und lesbare Weise hinzuzufügen. Insbesondere in diesem closure wiki page können Sie ein Beispiel sehr ähnlich zu dem, was Sie versuchen zu erreichen, finden

0

Dies ist natürlich Ihr Anruf, aber mit den meisten API-Demos, die ich verwendet habe, bevorzuge ich das längere Format, das Sie bei oben. Nachdem ich über den Code nachgedacht habe, mache ich normalerweise copy-and-paste, um zu überprüfen, dass die API funktioniert, wie ich denke, dass sie es dann von dort bearbeitet. Das Format zu ändern, um einige der sich wiederholenden Stücke zu verstecken, ist definitiv das, was du für die OO-Entwicklung machen willst, aber ich denke, dass dieser ein bisschen Demo-Code etwas ist, was die "sauberen Code-Götter" verstehen würden :-).

0

Es gibt keine Möglichkeit, dies in Java zu tun, aber versuchen Sie es mit groovy, wenn es für Sie möglich ist. Die andere Option, die Sie ähnlich verpacken können, ist aspect. siehe aspectj.

0

Ich habe gelernt, wie dies in Java getan wird, um eine Schnittstelle zu schaffen, die eine Methode hat. In Ihrem Code verwenden Sie Klassen, die diese Schnittstelle implementieren.