Reputation: 237
I have two classes and an interface shown below. Quick summary: Interface Winterface, Class Big, Class Little that extends Big and implements Winterface.
public interface Winterface {}
public class Big {
public int hello = 88;
public Big() {}
public void theMethod() {
System.out.println ("Big was here: " + (this instanceof Winterface) + ", " + this.hello);
}
}
public class Little extends Big implements Winterface{
private boolean hello = true;
public Little(){}
public void theMethod() {
super.theMethod();
System.out.println("Little was here: " + hello);
}
public static void main(String [] args) {
Little l = new Little();
l.theMethod();
}
}
When I execute the main in Little, I get the following output
Big was here: true, 88 Little was here: true
my question is, how can
1) (this instanceof Winterface) return true but
2) this.hello be 88? If this.hello = 88, then this = Big, which isn't an instance of Winterface.
I do not understand how this is possible, thanks in advance
EDIT: THANKS everyone I understand now that 'this' refers to little, which is a Big and implements Winterface. Since the method is being called as super.theMethod(), the variable 'hello' available is the one in Big even though 'this' refers to little.
Upvotes: 3
Views: 120
Reputation: 54074
l
is Little
but Little
is a Big
and also implements the behavior of Winterface
.
The super
is a call to the parent class so the hello
member of the parent class (i.e. Big
) is used.
You are not doing this.hello
but super.theMethod()
that uses the parent's class member variable hello
.
UPDATE:
The super.theMethod()
invokes the corresponding method in the parent class. In the parent class you access the fields of the parent (which also belong to the derived class since Little
is also a Big
). So the this.hello
at that point is accessing the part of the code that is of the parent class.
You can imagine the memory print of Little
as follows:
++++++++
+ Big +
--------
+Little+
++++++++
So Little
has all the members variables of the parent i.e. Big
and when the code runs inside super.theMethod()
it is running inside the "code area" of Big
.
As Peter states in his answer, polymorhism is not supported for methods and I hope that this overly simplistic description helps understand this
Upvotes: 2
Reputation: 428
What is happening here is that when you are defining your variable hello
in Little
you are not overwriting the variable hello
that is inside Big
you are defining a new variable hello
within Little
that is hiding the variable hello
within Big
. Thus within the scope of Big
, hello
will refer to the integer value of 88 and within the scope of Little
, hello
will refer to true. These are different variables both contained within your object, the only difference is the scope by which you refer to them.
Like others here have said, instanceof
is an operator that compares the runtime type of your object (what is returned by this.getClass()
). When in Big
even though the scope of the variables within your object will refer to Big
, this
is still of runtime type Little
which is why it is an instance of Winterface
.
Upvotes: 0
Reputation: 533530
this
can only be one class. However this.hello
is the field accessible to that class.
As this
can only be one class it is a Little
which has a parent Big
and implements Winterface
When you call a method in its parent which can only see hello
that is what it sees.
i.e. Java supports polymorphism for methods but not fields.
Upvotes: 2
Reputation: 4671
Your variable is an instance of Big and of Little. It's a direct instance of Little, but since Little inherits from Big the instanceof operator will return true for Big too.
Little l = new Little();
System.out.println(l instanceof Little); // true, l is an instance Little
System.out.println(l instanceof Big); // true, l is an instance of Little which inherits from Big
Your other misunderstanding (I'm assuming) is how the 'method lookup' works. When you call theMethod the it picks Little's implementation of that method. When you call super.theMethod though, you've explicitly said "call Big's version of this method", and then inside that method it's using Big's hello variable rather than Little's hello variable.
Upvotes: 0
Reputation: 31053
This is because the this instanceof ...
check does not use the static (i.e., compile-time) type (which is Big
), but the object's (this
') dynamic run-time type (i.e., this.getClass()
), which is Little
in your example. If it would use the static type, the operator would be pretty pointless, since we would have:
Object obj = "foo";
if (obj instanceof Object) { /* always entered */ }
/* but */ if (obj instanceof String) { /* never entered */ }
statically, at compile-time. The purpose of the instanceof
operator is to enable run-time type testing, for example:
Object obj = /* whatever */;
if (obj instanceof String) {
String str = (String)obj; // Cast cannot fail
...
} else if (obj instanceof Long) {
Long val = (Long)obj; // Cast cannot fail
...
}
Note, that this technique should only be used sparingly.
Upvotes: 1