Suppose the constructor of a superclass get called from a subclass and the subclass hides a method of the superclass the constructor calls. Then java uses the method from the subclass in the constructor of the superclass. But in most cases this is not the desired behavior, because the superclass gets not designed with the subclass in mind - it is the other way around.
How can one enforce the initialization with the superclasses own methods without making them final or static, renaming them or duplicating the code into the constructor? (Or does java not support/discourage using overridable methods in constuctors? If yes, then why? What is the hidden principle of this unsatisfying behavior?)
I tried an explicit cast...
((SuperClass) this).method()
... this does not work.
Example:
3 class SuperClass {
4 private int[] valField = new int[10];
5
6 SuperClass(int[] cloneField) {
7 for (int i = 0; i < 10; i++) set(i, cloneField[i]);
8 }
9
10 void set(int pos, int val) {
11 if (val < 0) throw new IllegalArgumentException("val must be positive; val was " + val);
12 if (pos < 0 || pos > 10) throw new IllegalArgumentException("pos must be within [0, 10]; pos was " + pos);
13 valField[pos] = val;
14 }
15
16 int get(int pos) {
17 return valField[pos];
18 }
20 }
6 class SubClass extends SuperClass {
7 private Set<Integer> isZero = new HashSet();
8
9 SubClass(int[] cloneField) {
10 super(cloneField);
11 isZero.clear();
12 for (int i = 0; i < 10; i++)
13 if (this.get(i) == 0)
14 isZero.add(i);
15 }
16
17 void set(int pos, int val) {
18 super.set(pos, val);
19 if (val == 0) isZero.add(pos);
20 else isZero.remove(pos);
21 }
22 }
This results in:
Exception in thread "main" java.lang.NullPointerException
at testingJava.SubClass.set(SubClass.java:19)
at testingJava.SuperClass.<init>(SuperClass.java:7)
at testingJava.SubClass.<init>(SubClass.java:10)
at testingJava.MainClass.main(MainClass.java:9)
EDIT: Some further testing and exploration revealed there is a weird solution. Splitting the superclass in two parts and using super.method() in the constructor seems to give the java interpreter a clear enough sign to let him sort out the right method.
Example:
class SuperClass {
void message() {
System.out.println("I am the super class.");
}
}
class MiddleClass extends SuperClass {
MiddleClass() {
super.message();
}
}
class SubClass extends MiddleClass {
void message() {
System.out.println("I am the sub class.");
}
}
Now...
SubClass mySubClass = new SubClass();
...evaluates to:
I am the super class.