Cole Canning
Cole Canning

Reputation: 237

I do not understand 'this' being used with a superclass

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

Answers (5)

Cratylus
Cratylus

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

JeffS
JeffS

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

Peter Lawrey
Peter Lawrey

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

Chris
Chris

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

Dirk
Dirk

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

Related Questions