27 votes

Comment utiliser les champs dans l'énumération Java en remplaçant la méthode?

La tâche consiste à implémenter un beau modèle de conception de stratégie avec le java enum :

 public enum MyEnum {

    FIRST {
        @Override
        public String doIt() {
            return "1: " + someField; //error
        }
    },
    SECOND {
        @Override
        public String doIt() {
            return "2: " + someField; //error
        }
    };

    private String someField;

    public abstract String doIt();

} 
 

mais en faisant référence à someField je reçois

Impossible de faire une référence statique au champ non statique someField.

Qu'est-ce qui ne va pas et est-il possible de faire mieux?

22voto

raphw Points 6008

Spécialisée enum n'est rien mais une sous-classe à l'intérieur de la classe sémantique. Si vous regardez le code octet après compilation, vous verrez que le compilateur insère uniquement méthode d'accesseur pour la lecture d'un domaine privé, mais spécialisé enum est réalisé de sa propre classe. Vous pouvez penser au sujet de votre enum que la mise en œuvre:

public abstract class MyEnum {

  private static class First extends MyEnum {

    @Override
    public String doIt() {
        return "1: " + someField; //error
    }
  }

  private static class Second extends MyEnum {

    @Override
    public String doIt() {
        return "2: " + someField; //error
    }
  }

  public static final MyEnum FIRST = new First();
  public static final MyEnum SECOND = new Second();

  private String someField;

  public abstract String doIt();
} 

Comme vous pouvez le voir, le même compilateur des erreurs se produisent. Effectivement, votre problème ne concerne pas enums, mais à l'intérieur de la classe sémantique.

Cependant, vous avez trouvé un cas limite du compilateur de deviner l'intention de votre code et de vous avertir que ce que vous avez l'intention est illégal. En général, l' someField champ est visible à tout spécialisée enum. Cependant, il y a deux manières d'accéder à l' private domaine à partir d'un noyau de classe et un seul est légal:

  1. private des membres ne sont pas héritées. Vous ne pouvez donc pas accéder à un private champ d' this instance où elle a été définie dans une classe super.

  2. Pour les classes internes, les membres de l'classes sont accessibles, même si elles sont private. Ceci est réalisé par le compilateur en insérant des méthodes d'accès à l'extérieur des classes qui exposent l' private champs par des méthodes accesseurs. Un non-static champ ne peut être accessible que si l'intérieur de la classe est non-static. Pour enums, les classes internes sont cependant toujours static.

Le plus tard condition est que le compilateur se plaint:

Ne peut pas faire une référence statique pour les non-champ statique someField

Vous essayez d'accéder à une non-static de static intérieur de la classe. Ce n'est pas possible, même si le champ doit être techniquement visible que de l'intérieur de la classe sémantique. Vous pourriez demander au compilateur explicitement pour accéder à la valeur par la lecture de la super-classe, par exemple:

public String doIt() {
  MyEnum thiz = this;
  return thiz.someField;
}

Maintenant que le compilateur sait que vous essayez d'accéder à un membre d'un visible (extérieur) - type au lieu de tort accès à l' someField domaine de la (non statique) externe instance de classe (qui n'existe pas). (De même, vous pouvez écrire super.someField qui exprime la même idée que vous voulez aller en bas de la chaîne d'héritage et de ne pas accéder à l'extérieur de l'instance du champ.) La solution facile serait cependant tout simplement de rendre le champ protected. De cette façon, le compilateur est heureux au sujet de l'héritage de la visibilité et de la compilation de vos installation d'origine.

4voto

Alex Points 1092

Si vous faites someField protégé au lieu de privé ou utilisez super.someField place, vous pourrez y accéder.

2voto

Tim B Points 19851

someField est privé, supprimez le modificateur privé ou déplacez-le dans vos classes abstraites.

2voto

icza Points 3857

Les champs privés ne sont pas accessibles à partir des sous-classes, ce qui est exactement ce que vous faites lorsque vous implémentez la méthode abstraite MyEnum.doIt() par instance. Modifiez-le en protected , et cela fonctionnera.

1voto

Szymon Krawczyk Points 33

someField est une variable privée lorsque les énumérations sont des variables statiques. Vous ne pouvez pas affecter une variable non statique à une variable statique de cette manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X