Подтвердить что ты не робот

Как переопределить/расширить внутренний класс из подкласса?

Я хочу изменить метод выполнения класса без переопределения метода и только переопределить (или идеально расширить) внутренний класс. Предположим, что я не могу изменить тот факт, что мне нужно это сделать (я изменяю существующую базу данных с открытым исходным кодом, и было бы трение для вытаскивания классов или еще чего-то).

public class A {
  static class Thing {
    public int value() { return 10+value2(); }
    public int value2() { return 10; }
  }

  public String toString() {
    Thing t = new Thing();
    return Integer.toString(t.value());
  }
}

public class B extends A {
  static class Thing {
    public int value2() { return 20; }
  }
}

Моя цель состоит в том, чтобы изменить только Thing, получив B toString(), чтобы вернуть "30", где в настоящее время он вернет "20". Идеальным было бы изменить только метод value2 (таким образом, оставив любые другие методы без изменений), но я не знаю, возможно ли это.

Спасибо

4b9b3361

Ответ 1

Я думаю, для этого вам нужен метод factory. Рассмотрим следующий пример (полученный из вашего фрагмента):

static class A {
    static class Thing {
        public int value() {
            return 10 + value2();
        }
        public int value2() {
            return 10;
        }
    }
    protected Thing createThing() {
        return new Thing();
    }
    public String toString() {
        return Integer.toString(createThing().value());
    }
}

static class B extends A {
    static class Thing extends A.Thing {
        public int value2() {
            return 20; 
        }
    }
    @Override
    protected Thing createThing() {
        return new Thing(); // creates B.Thing
    }
}

public static void main(String[] args) {
    System.out.println(new B());
}

Вывод:

30

Ответ 2

Вы должны иметь возможность просто расширить внутренний класс, когда Thing расширяет A.Thing. Пока это видно в вашей области, это не должно быть проблемой.

Ответ 3

Это невозможно, только изменяя значение2. Проблема в том, что "новые" вызовы не отправляются динамически - "новый" в toString всегда будет создавать A:: Thing. Вы можете исправить это, создав factory: что-то вроде этого:

public class A {
  static class Thing {
    public int value() { return 10+value2(); }
    public int value2() { return 10; }
  }

  private Thing makeThing() { return new Thing(); }


  public String toString() {
    Thing t = new Thing();
    return Integer.toString(t.value());
  }
}

public class B extends A {
  static class Thing extends A.Thing {
    public int value2() { return 20; }
  }

  private Thing makeThing() { return new Thing(); }

}