2010-02-05 3 views
9

J'écris du code démo pour une API que nous avons créée et je continue à courir dans le même problème où je me répète, encore et encore ad nauseum. Je suis douloureusement conscient que Java est prévu pour avoir des fermetures ajoutées, mais je n'ai pas accès à eux maintenant. Voici ce qui se répète partout que je voudrais boîte juste dans son propre petit coin:Composer des fonctions 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; 
    } 
} 

A propos de la seule façon que je l'ai pensé pour aller contourner ce problème est en passant un Method en fonction qui porte avec elle la logique try-catch et enveloppant le tout dans une autre fonction comme ceci:

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

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

mais il semble laid et comporte beaucoup de passe-partout. Existe-t-il un moyen plus simple de composer des fonctions en Java?

+0

Je pense que certains le projet extensions pour les fermetures en Java semblent encore plus laids. – DerMike

Répondre

8

en Java c'est très difficile car il n'y a pas de support de première classe pour les fonctions (contrairement à clojure ou scala et probablement autre).

Cependant, vous pouvez encapsuler l'opération dans un objet:

interface Function<R, T> { 

    R call(T... input); 
} 

refactoriser puis Foo comme:

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

Suggérez-vous alors que ceux-ci soient faits comme classes privées au sein de la plus grande classe 'Foo'? Je pense que c'est une assez bonne séparation des préoccupations. Btw, j'aime Scala. – wheaties

2

Essayez lambdaj. Cela permet d'ajouter un peu de FP à Java de manière très légère et lisible. En particulier dans ce closure wiki page vous pouvez trouver un exemple très similaire à ce que vous essayez d'atteindre,

0

Ceci est évidemment votre appel, mais avec la plupart des démos API que j'ai utilisé, je préfère le format plus long que vous avez à la Haut. Après avoir regardé le code, je fais généralement un copier-coller pour vérifier que l'API fonctionne comme je le pense, puis je le modifie à partir de là. Changer le format pour cacher certaines des pièces répétitives est définitivement ce que vous voulez faire pour le développement OO mais je pense que ce code de démo est quelque chose que les «dieux du code propre» comprendraient :-).

0

Il n'y a aucun moyen de le faire dans Java, mais essayez d'utiliser groovy si c'est possible pour vous. L'autre option que vous pouvez avoir un habillage similaire utilise l'aspect. voir aspectj.

0

J'ai appris la façon dont cela est fait en Java est de créer une interface qui a une méthode. Dans votre code, vous utilisez des classes implémentant cette interface.