0

Prenons l'exemple suivant:Annotation pour soutenir refactoring d'une interface fonctionnelle

public interface Greeter { 
    String greet(); 
} 

public class ExplicitGreeterImpl implements Greeter { 
    @Override 
    public String greet() { 
     return "Hello World!"; 
    } 
} 

public class ImplicitGreeterImpl { 
    public String doTheGreeting() { 
     return "Hello World!"; 
    } 
} 

private void run() { 
    System.out.println(new ExplicitGreeterImpl().greet()); 

    Greeter foo = new ImplicitGreeterImpl()::doTheGreeting; 
    System.out.println(foo.greet()); 
} 

L'interface fonctionnelle Greeter a deux implémentations. ExplicitGreeterImpl implémente Greeter en utilisant la clause , alors que ImplicitGreeterImpl::doTheGreeting implémente Greeter sans elle. Néanmoins, ImplicitGreeterImpl::doTheGreeting est conçu pour mettre en œuvre Greeter, tout comme ExplicitGreeterImpl.

Maintenant, je veux factoriser l'interface Greeter, donc je peux passer un nom à lui:

public interface Greeter { 
    String greet(String name); 
} 

Je peux faire cela avec le changement Méthode Signature refactoring fourni par Eclipse (je suis sûr que d'autres Les IDE ont un refactoring similaire). Cela met automatiquement à jour toutes les implémentations et les utilisations de l'interface Greeter. Les implémentations reçoivent le nouveau paramètre, tandis que les utilisations transmettent une valeur par défaut configurable. Cela fonctionne très bien pour le ExplicitGreeterImpl, cependant le refactoring ne touche pas la méthode ImplicitGreeterImpl::doTheGreeting. Ainsi, l'affectation

Greeter foo = new ImplicitGreeterImpl()::doTheGreeting; 

devient une erreur de compilation. Pour résoudre ce problème, je dois ajuster manuellement la signature de la méthode ImplicitGreeterImpl::doTheGreeting.

Maintenant, je comprends qu'il n'est pas souhaitable dans de nombreux cas d'ajuster automatiquement la signature de ImplicitGreeterImpl::doTheGreeting. Cependant, je pense que le flux de travail actuel peut être amélioré:

  • Eclipse n'affiche un avertissement dans l'aperçu de refactoring qui suggère qu'il y aura une erreur de compilation.
  • Il devrait être possible d'annoter la méthode pour clarifier qu'elle est supposée implémenter une interface fonctionnelle donnée.

Par exemple, ImplicitGreeterImpl pourrait ressembler à ceci:

public class ImplicitGreeterImpl { 
    @Implements(Greeter.class) 
    public String doTheGreeting() { 
     return "Hello World!"; 
    } 
} 

Maintenant, les outils de refactoring pourrait être sûr que ImplicitGreeterImpl::doTheGreeting est censé mettre en œuvre Greeter et donc, ils peuvent changer automatiquement sa signature. Par conséquent, ma question est la suivante: existe-t-il un moyen de dire aux outils de refactoring qu'une méthode donnée est supposée implémenter une interface fonctionnelle donnée? J'ai cherché l'annotation proposée ci-dessus, mais je n'ai rien trouvé d'utile.

Répondre

0

J'ai continué à chercher une réponse, mais il ne semble pas y avoir de solution utilisant une annotation. Cependant, lorsque je posais la question, j'avais un cas d'utilisation spécifique à l'esprit: je veux écrire de nombreuses implémentations différentes de la même interface fonctionnelle dans un seul fichier.En effet, il y a une solution à ce problème, qui fonctionne également très bien avec des outils automatiques de refactorisation:

public interface Greeter { 
    String greet(); 
} 

public enum EnumGreeterImpl implements Greeter { 
    GREETER1 { 
     @Override 
     public String greet() { 
      return "Hello World!"; 
     } 
    }, 
    GREETER2 { 
     @Override 
     public String greet() { 
      return "Foo bar"; 
     } 
    }, 
} 

private void run() { 
    Greeter foo = EnumGreeterImpl.GREETER1; 
    System.out.println(foo.greet()); 
} 

Voir aussi:

0

Oui: vous devez implémenter l'interface. Si vous pouvez ajouter une annotation liant à l'interface, pourquoi ne pas l'implémenter?

+0

Il est en fait un bon raison de ne pas implémenter l'interface directement, mais d'utiliser la référence de la méthode. Considérez le modèle de commande. Dans ce cas: (1) L'interface de commande est probablement une interface fonctionnelle, (2) il y a beaucoup d'implémentations de l'interface de commande et (3) chacune de ces implémentations est très simple. L'ajout d'une classe supplémentaire pour chacune de ces implémentations ajoute beaucoup de bruit au code. Cependant, si chaque implémentation de commande est juste une méthode, le code devient beaucoup plus propre. –