0

I'm new to Java and I'm trying to understand what would happen when I assign a child class instance to a parent class instance variable by simulating the following program.

public class ConfusionWithInheritance {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        DerievedClass d = new DerievedClass();
        BaseClass b = BaseClass.class.cast(d);
        BaseClass b1 = new DerievedClass();
        b.doSomeJob();
        b.printMagic(); //-> Compiler shouted me that it didn't know this method here.
    }
}
class BaseClass {
    public void doSomeJob() {
        System.out.println("Printing Value X");
    }
}
class DerievedClass extends BaseClass {
    public void doSomeJob() {
        System.out.println("Printing Value Y");
    }
    public void printMagic() {
        System.out.println("Printing magic...");
    }
}

1) Why am I allowed to assign an instance of a child class to a parent type variable?

2) From this answer, it's explained that since I'm telling the blue print of the class to be - the parent class - it knows only the methods in the parent class. Then why it's printing the value in the method of child class when I'm invoking childInstance.doSomeJob()?

Tom Taylor
  • 3,344
  • 2
  • 38
  • 63
  • The second answer becomes clear if you add `@Override public void doSomeJob() {` and see that you're allowed to do that. While if you did for the other method, you'd get a compiler error. – EpicPandaForce May 26 '19 at 12:26
  • 2
    There is no good reason to write `SomeClass.class.cast(d)`: `(SomeClass) d` is more concise, and offers more compile-time checking. – Andy Turner May 26 '19 at 12:39
  • 3
    `Animal a = new Dog();`. A `Dog` **is** an `Animal`. So it makes sense that you can assign it to such a variable. Differentiate variables from instances. The variable still refers to an actual dog. It's just that the variable says *"hey, i can refer to everything that is Animal"*. Although the instance is a dog and technically `a.bark()` would work, Java protects you from this. Since you could do `a = new Cat()` and then it would not work anymore. Type information can be retrieved back by **casting** `((Dog) a).bark()`. Although this in general highlights a bad design. – Zabuzard May 26 '19 at 12:48
  • 1
    Possibly related: [What does it mean to “program to an interface”?](https://stackoverflow.com/q/383947) – Pshemo May 26 '19 at 12:51

2 Answers2

1

When creating an object:

BaseClass b1 = new DerievedClass();

What we're saying is:

ReferenceType variableName = new ConcreteImplementation();

Think of it as the ReferenceType providing a scaffold for a new Object.

When an object is created it looks to this ReferenceType and creates an object with all the methods in ReferenceType as a skeleton.

Then we look at the ConcreteImplementation for the implementation of the methods. So the compiler looks to ConcreteImplementation to fill in all the methods.

Only what's defined in ReferenceType is implemented in the final object.

Think of casting as changing the ReferenceType of an already existing object

With the line:

DerievedClass d = new DerievedClass();

ReferenceType is DerievedClass so we take all the methods from DerivedClass and fill them in with the implementation from the ConcreteImplementation which is DerivedClass.

Then we're casting DerievedClass d to BaseClass b.

BaseClass b = BaseClass.class.cast(d);

d has all the implementation from DerivedClass but the scaffold came from the ReferencType BaseClass so we can't call printMagic because it doesn't exist in BaseClass.

Does that make sense?

Hope it helps

Cwrwhaf
  • 324
  • 3
  • 5
1

This boils down to there being a difference between compile time and runtime.

At compile time, the methods available are those in the type the object is declared with.
At runtime, the methods invoked are those in the type the object is instantiated with.

So with an object that's declared as type BaseClass and instantiated as type DerivedClass, the methods available will be those in BaseClass, ie. doSomeJob(), but the method invoked is the one in DerivedClass.

Nathan Adams
  • 1,255
  • 1
  • 11
  • 17