2010-09-03 4 views
3

Dans mon projet, j'ai défini l'une annotation similaire à ce qui suit:
(Omettre @Retention, @Target par souci de concision)Java Annotation Overloading?

public @interface DecaysTo { 
    String[] value(); 
} 

Depuis l'écriture à l'origine il, nos besoins ont changé et j'ai maintenant défini un ENUM que je veux être en mesure d'utiliser à la place de la chaîne:

public enum Particle { 
    ELECTRON, 
    ANTIELECTRON, 
    NEUTRINO, 
    ANTINEUTRINO, 
    ... 
} 

pour éviter la mise à jour tous les cas de cette annotation, je voudrais être en mesure de construire l'annotation avec soit a Stringou un membre de enum Particlesans devoir mettre à jour chaque instance de cette annotation pour spécifier l'attribut. Cependant, puisque nous définissons les attributs de l'annotation, et non les constructeurs, il semble impossible de la surcharger.

// In a perfect world, either of these would work ... 
public @interface DecaysTo { 
    String[] value(); 
    Particle[] value(); 
} 

@DecaysTo({"Electron", ...}) 
@DecaysTo({Particle.ELECTRON, ...}) 

// without having to explicitly specify which attribute to set: 
public @interface DecaysTo { 
    String[] stringVals(); 
    Particle[] enumVals(); 
} 

@DecaysTo(stringVals = {"Electron", ...}) 
@DecaysTo(enumVals = {Particle.ELECTRON, ...}) 

également essayé:

public @interface DecaysTo { 
    Object[] value(); 
} 

Y at-il une façon de faire qui n'implique pas retourner à travers et l'édition d'une énorme quantité de code?

Répondre

4

Le meilleur moyen est de trouver et de remplacer toutes les annotations précédentes. Vous ne voulez pas que l'ancien design traîne. Gardez une base de code propre tout au long des refactorings. Supposons que vous ne voulez pas faire cela, ou que vous ne possédez pas le code qui utilise l'annotation, vous devriez garder deux types d'annotations. Dans votre code de traitement des annotations, vous recherchez les deux, et si l'ancien est utilisé, convertissez-le en nouveau.

DecaysToV2 anno = getAnnotation(DecaysToV2.class); 
if(anno = null) 
{ 
    DecaysTo anno_old = getAnnotation(DecaysTo.class); 
    if(anno_old!=null) 
     anno = convert (anno_old); 
} 

DecaysToV2 est juste une interface que vous pouvez impl:

DecaysToV2 convert(DecaysTo old) 
{ 
    DecaysToV2Impl impl = new DecaysToV2Impl(); 
    impl.value = ... 
    return impl; 
} 
static class DecaysToV2Impl implements DecaysToV2 
{ 
    Particle[] value; 
    public Particle[] value(){ return this.value; } 
} 
+0

À quoi ressemblerait cette méthode de conversion? Voulez-vous dire faire un proxy dynamique vous-même, ou quelque chose d'autre? – Yishai

2

Vous pouvez simplement déprécier cette annotation et en introduire une nouvelle (disons @DecaysToParticle) pour le nouveau code.

1

Peut-être ce que vous avez vraiment besoin est

enum Particle { 
    ELECTRON("Electron"), 
    ... 

    private String name; 
    private Particle(String name) { 
     this.name = name; 
    } 
    public String getName() {return name;} 
} 

(Vous pouvez également générer le nom avec des fonctions de chaîne, mais apporach est plus flexible).

Aussi je ne comprends pas quelle énorme quantité de code doit être changé, puisque (je devine) vos suggestions ne compileraient pas, j'espère que ce n'est pas ce que votre code ressemble réellement.