Поля в объекте инициализируются значением по умолчанию, равным нулю или 0, когда объект создается впервые, затем фактически запускается ваш конструктор, который вызывает суперконструктор в качестве своего первого шага.
К сожалению, вы не можете обойти это, написав свой конструктор как
Child() {
i=100;
super();
}
И, не имея возможности сделать это, невозможно установить дочернее поле i
до того, как оно будет использовано в вызове метода переопределения из родительского конструктора.
Однако стоит знать несколько способов обойти это:
Подход заключается в том, чтобы скрыть i
за абстрактным геттером и предоставить статическую фабричную функцию, которая создает новые экземпляры, переопределяющие getI
.
public class Child extends Parent {
protected abstract getI();
@Override void printIt() {
System.out.print("i = " + i);
}
static Child create(final int i) {
return new Child() {
int getI() { return i; }
}
}
}
Child child = Child.create(100);
Другой подход состоит в том, чтобы отделить printIt
от иерархии Родитель/Дочерний элемент. Затем вы можете создать принтер до вызова родительского конструктора. (Часто этот трюк можно использовать, чтобы полностью выпотрошить Child, оставив вам только класс Parent и компоненты — то есть вы в конечном итоге используете композицию, а не наследование.)
class Parent {
public interface Printer {
void printIt();
}
public class DefaultPrinter extends Printer {
@Override void printIt() {
System.out.println("Default Printer...");
}
}
Parent() {
this(new DefaultPrinter());
}
Parent(Printer p ) {
this.printer = p;
printIt();
}
void printIt() {
p.printIt();
}
}
public class Child extends Parent {
public class ChildPrinter implements Parent.Printer {
final int i = 100;
@Override void printIt() {
System.out.println("i = "+i);
}
}
Child() {
super( new Printer() );
}
}
person
Michael Anderson
schedule
29.07.2014