Reputation: 1069
Currently doing a practice test on abstract classes and interfaces and ran into this problem:
public class Test {
public static void main(String[] args) {
new Circle9();
}
}
public abstract class GeometricObject {
protected GeometricObject() {
System.out.print("A");
}
protected GeometricObject(String color, boolean filled) {
System.out.print("B");
}
}
public class Circle9 extends GeometricObject {
/** Default constructor */
public Circle9() {
this(1.0);
System.out.print("C");
}
/** Construct circle with a specified radius */
public Circle9(double radius) {
this(radius, "white", false);
System.out.print("D");
}
/** Construct a circle with specified radius, filled, and color */
public Circle9(double radius, String color, boolean filled) {
super(color, filled);
System.out.print("E");
}
}
Why is the output BEDC? I thought new Circle9() would first invoke the no-arg constructor of the Circle 9 class, printing A, and then the other letters, but I'm having a hard time understanding the path of the code.
Upvotes: 2
Views: 953
Reputation: 209004
this question doesnt really have anything to do with abstract classes or interfaces. It's more about inheritance.
Your answer is this. When you call a subclass, it's superclasses are first called, WITH their no-arg consructor, UNLESS you explicitly call a different constructor, which you have. when you call:
Circle9()
which
this(1.0)
calls
Circle(doubleradius)
which
this(radius, "white", false)
calls
Circle(double, string, boolean)
which
super(Color, filled)
calls
GeometricObject(string, boolean)
which is the last in the inheritance chain, so its actions are performed first
print("B")
then the program runs backward through the chain and prints the rest according to position in the chain, the same way it moved forward, is the same way it will go backward, hence
print("E")
print("D")
print("C")
Upvotes: 1
Reputation: 425043
Follow the call stack:
Upvotes: 5
Reputation: 39950
Constructors are somewhat special - with the exception of Object()
, each constructor in any class must call one, and only one other constructor, either in the current class or its superclass, before any other code in it runs. You can choose which constructor this is either explicitly, by using this(...)
or super(...)
. If you do not do this, only then will the no-args constructor of the superclass be implicitly called. (As if you used super()
.)
Which means you can consider this as a dependency chain that starts with the constructor you're invoking with new
, and ultimately has to reach Object()
. In your example, this chain would be:
Circle9() => prints "C"
|
| (explicit)
v
Circle9(double) => prints "D"
|
| (explicit)
v
Circle9(double,String,boolean) => prints "E"
|
| (explicit)
v
GeometricObject(String, boolean) => prints "B"
|
| (implicit)
v
Object() => does nothing
You then run the actual code in the constructors, walking this chain backwards.
The reason why "A"
is never printed is that GeometricObject()
never gets called because neither constructor of Circle9
nor GeometricObject(String,boolean)
calls ("depends on") it - they all explicitly call some other constructor.
Upvotes: 5
Reputation: 2027
The no-arg constructor of the Circle9 class prints C, not A.
Your order of calls is:
new Circle9();
new Circle9(double);
new Circle9(double, String, boolean);
new GeometricObject(String, boolean);
System.out.print("B");
System.out.print("E");
System.out.print("D");
System.out.print("C");
GeometricObject() is never called; if GeometricObject(String, boolean) explicitly called this()
as its first line, you'd see A, but it's not called by default from another constructor. (A constructor must be called to make the object, but nothing requires that the no-args constructor be called from a constructor that has arguments, nor vice versa.)
Upvotes: 4
Reputation: 7624
In this case, the empty constructor of the Circle9 class calls the double constructor of the Circle9 class which calls the radius, String, boolean constructor of the Circle9 class which calls the String, boolean super constructor of the GeometricObject class. This then works backwards as functions return - B (Geometric Object), E - Third Circle 9, D - Second Circle9, C - First Circle9.
Upvotes: 1
Reputation: 14164
Calling new Circle9()
does not invoke the no-arg superclass constructor, it goes off elsewhere. Read your own code.
public Circle9() {
this(1.0); // calls to Circle(double radius) constructor, & on from there..
System.out.print("C");
}
Upvotes: 0