javainheritanceextends

java do extended classes have two types


In java I have the following:

ClassA obj = new ClassB();

where ClassB extends ClassA. Is obj of type ClassA or ClassB or both?

if we have instead:

ClassB obj = new ClassB();

it seems clear that obj is of type ClassB but all ClassB are ClassA too, aren't they? So is the type both ClassA and ClassB?

if we add the following:

ClassA [] objects = new ClassA[3];
ClassA obj = new ClassB();
objects[0] = obj;

it seems that obj is of type ClassA. So we can add it to objects even though obj is a new ClassB();

Here's my confusion, let say we have an overwritten method in ClassB from ClassA, I can call the method and I get the expected output from the ClassB overwritten method. But, if I have just a ClassB method not also contained in ClassA I can't call it and I don't seem to be able to upcast it to ClassB. oh wait, obj is of type ClassA so we can't cast it to a ClassB because all ClassA's aren't ClassB's.

So obj is of type ClassA but we set it to new ClassB(). so what the heck is it? Is it ClassA or ClassB, I'm so confused. Why can we access the overwritten methods in ClassB but not the non overwritten methods? Is that just the way polymorphism works?


Solution

  • Your question is identical to this situation:

    You see Max, who is a poodle. You ask: So, what's the deal? Is Max a Poodle, a Dog, or an Animal? Or all three at the same time?

    The answer is more or less 'that question belies a misunderstanding of how we classify living things'. If you must choose from your limited set of options, "It is all 3" is more correct than any other. But that implies you could create a Poodle that is also an Animal but not a Dog, and that is the wrong conclusion: Anything that is a poodle is necessarily also a Dog.

    It also depends on context. If I ask about the 'type' of creature that Max is, and the situation calls for just one answer, you always get 'Poodle'. Because that's the most useful answer - knowing that max is a Poodle is enough to determine that max is therefore necessarily also a dog and also an animal because by definition, all poodles are. You can't have a non-dog creature that is nevertheless a poodle.

    Hence:

    Poodle max = new Poodle();
    Animal a = max;
    System.out.println(a.getClass()); // prints 'Poodle'.
    

    Remember, the dot operator is 'follow the address on the post-it and ask the thing you find there a question'. .getClass() doesn't 'ask the question' to a, it asks the question to the thing a is pointing at. Currently, a is pointing at max. And if you ask Max what he is (and if dogs could speak, I guess), max would say 'I am a poodle'. Max won't say "I am an animal"; max has no awareness of the postit note, and really couldn't: There could be 85 postits all with the address of max. There could be none left (local variables cease existing once a method ends, for example, as if the postit note poofs into oblivion). When asking questions to objects they don't get the 'context' (what route you used to find that object), and thus you know their answer cannot possibly be dependent on it.