Frage

Es gibt eine abstrakte Klasse:

public abstract class AbstractAny {
  private long period;

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

Ich will nicht die Quelle der abstrakten Klasse ändern, aber hinzufügen muß eine gewisse Flexibilität auf, wie die Feldperiode festgelegt wird. Ist es möglich, den Wert der Feldperiode von einer überschriebenen Methode zu ändern? Wie zum Beispiel:

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);
    }
  }
}

Wenn ich versuche, diesen Code auszuführen super.getClass().getDeclaredField("period") java.lang.NoSuchFieldException: period wirft

War es hilfreich?

Lösung

Sie müssen getClass().getSuperclass() die übergeordnete Klasse zu bekommen, nicht super.getClass().

Allerdings I wirklich Sie tun dies nicht empfehlen. Sie zerstören im Grunde die Kapselung der abstrakten Klasse. Wenn die abstrakte Klasse ist nicht genug Flexibilität für seine Nachkommen bereitstellt, sollte es festgelegt werden - geht um es nur Ärger bringen wird. Was passiert, wenn ein anderes Mitglied der abstrakten Klasse muss geändert werden, wann immer dies tut? Der ganze Sinn der privaten Zustand aufweist, so dass die Klasse in der Lage ist, seine eigenen Daten zu schützen. Mit Reflexion wie dies eine wirklich hässliche Hack ist, die eine absolute letzte Mittel sein sollte.

Andere Tipps

ich mit Jon Skeet bin. Es ist einfacher, auf lange Sicht zu den Source-Code der übergeordneten Klasse ändern entweder dieses Feld machen geschützt oder Mutation zu einer überschreibbare Methode zu delegieren. Mit Reflexion des Wert ändern jetzt funktioniert ok, aber es nicht sehr gut skalieren bis Wartung im Laufe der Zeit geht.

ConcreteSome erweitert nicht die abstrakte Klasse AbstractAny.
Versuchen Sie, diese

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

sollte java.lang.Object zurückkehren

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top