Question

Il existe une classe abstraite:

public abstract class AbstractAny {
  private long period;

  public void doSomething() {
    // blah blah blah
    period = someHardcodedValue;
    // blah blah blah
  }
}

Je ne souhaite pas changer la source de la classe abstraite, mais je dois ajouter une certaine flexibilité dans la définition de la période de champ. Est-il possible de changer la valeur de la période sur le terrain d'une méthode surchargée? Comme par exemple:

public class ConcreteSome extends AbstractAny{
  @Override
  public void doSomething() {
    try {
      Field p = super.getClass().getDeclaredField("period");
      p.setAccessible(true);
      p.setLong(this, 10L);
    } catch (SecurityException e) {
        throw new RuntimeException(e);
    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
  }
}

Lorsque j'essaie d'exécuter ce code super.getClass (). getDeclaredField ("période") lève java.lang.NoSuchFieldException: period

Était-ce utile?

La solution

Vous avez besoin de getClass (). getSuperclass () pour obtenir la superclasse, et non de super.getClass () .

Cependant, je vraiment ne recommande pas de faire cela. Vous détruisez fondamentalement l'encapsulation de la classe abstraite. Si la classe abstraite n'offre pas suffisamment de flexibilité à ses descendants, elle doit être corrigée - la contourner, c'est simplement poser des problèmes. Que faire si un autre membre de la classe abstraite doit être changé chaque fois que celui-ci le fait? L'intérêt d'avoir un état privé est de permettre à la classe de protéger ses propres données. Utiliser une réflexion comme celle-ci est un vilain bidon qui devrait être un dernier recours absolu.

Autres conseils

Je suis avec Jon Skeet. À long terme, il est plus facile de modifier le code source de la superclasse afin de protéger ce champ ou de déléguer la mutation à une méthode pouvant être remplacée. L'utilisation de la réflexion pour modifier la valeur fonctionne bien à présent, mais elle ne s'adapte pas très bien en termes de maintenance.

ConcreteSome n'étend pas la classe abstraite AbstractAny.
Essayez ceci

public class ConcreteSome {
    @Override
    public void doSomething() {
        Class<?> clazz = getClass().getSuperclass();
        System.out.println(clazz);
        Field p = clazz.getDeclaredField("period");
        ...

doit renvoyer java.lang.Object

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top