Reputation: 190
class Foo {
int number;
public Foo(int x) {
number = x;
multiply();
}
public void multiply() {
number = 2 * number;
}
public int getNumber() {
return number;
}
}
class Bar extends Foo {
int number;
public Bar(int x,int y) {
super(x);
number = y;
multiply();
}
public void multiply() {
number = number * 3;
}
}
class Test {
public static void main(String args[]) {
Foo foo = new Foo(42);
Foo bar = new Bar(42,24);
System.out.println(foo.getNumber() + "\n" + bar.getNumber());
}
}
The output of this code is 84 and 42 but no matter how I trace it, I end up with 84 and 72. Can anyone explain this in detail.
Upvotes: 2
Views: 111
Reputation: 23012
In second case in Foo bar = new Bar(42,24);
for super(x)
,
public Foo(int x) {
number = x;//Now number in Foo is 42
multiply();// of Bar will be called not of Foo
//but currently number is 0 in Bar
}
Indirectly Foo#multiply();
has no effect in your second case for the number
in Foo
. So, multiply();
of Bar
is called in constructor of Foo
, your x
which is now number
in Foo
remains unchanged which is 42
. i.e. Bar(100,24)
will give you number 100
in your case.
You have not override the getNumber
in Bar
you will have the number
from the Foo
which is 42
.
Worth to note that number
in Bar
is now 72
because of number = y
and multiply
method of Bar
, which you have not used.
Your constructor of Foo
is similar to,
public Foo(int x) {
number = x;
this.multiply();// In second case 'this' refers to Bar and not Foo
//So that control goes to multiply method of Bar and not Foo
}
Upvotes: 1
Reputation: 34648
Here is a trace:
Calling new Bar(42,4)
:
The 42
is passed to the super
constructor. So it executes the body of:
public Foo(int x) {
number = x;
multiply();
}
The number
it uses is its own number
(the Foo.number
which is hidden), but the multiply()
it calls is the overridden one. Thus it calls:
public void multiply() {
number = number * 3;
}
But this refers to Bar.number
, which at this stage is still 0
as it has not been initialized. So it remains 0. The number
in Foo
is not affected because that's not the number
that appears in this version of multiply
.
So at the moment we have Foo.number
at 42, and Bar.number
at 0.
We next continue to
number = y;
multiply();
Which puts the 24 in Bar.number
, then multiplies it by 3.
But the getNumber()
is not overridden. Which means that when you call bar.getNumber()
you'll actually be getting the number
from the Foo
inside it. Which is 42.
Upvotes: 5