0
package sample;

A very simple question in Java, When I am trying to do like

Parent parent = new Child(); // Works

but the other way is not possible. Like Child child = new Parent(); Why?

Secondly, what is the difference between instantiating child like

Child c = new Child(); vs Parent p = new Child();

When should I use what?

Code snippet below:

public class A{

    public void display(){
        System.out.println("hello");
    }
}

class B extends A {
    public void display(){
        System.out.println("hi");
    }

    public static void main(String args[]) {
        A a = new B();//works
        a.display();
        
        B b = new A();// doesnt work
    
    }
} 
Poppy
  • 2,902
  • 14
  • 51
  • 75
  • 2
    Every dog is an animal; All animals are not dogs => Every `B` is `A`. All `A` are not `B`. This is why when you have a `B`, you can assign it to an `A` instance. When you have an `A` instance, you can't assign it to a `B` variable. That's because not all `A`s are `B`. – ernest_k Jul 01 '21 at 18:00
  • 1
    Lets say you add in `B` class some new field or method. If `B b = new A();` would be possible then `System.out.println(b.newField)` should also be valid. But `b` holds object of type `A`, and that type doesn't have `newField` so what should be result here? Probably some kind of exception, but this means we just broke Java's type-safety which is one of main reason people use that language. This problem doesn't exist with `Parent p = new Child()` since we are sure that Child inherits from Parent everything which can be accessed via `p`. – Pshemo Jul 01 '21 at 18:07
  • 2
    Regarding "When should I use what?" see [What does it mean to “program to an interface”?](https://stackoverflow.com/q/383947) – Pshemo Jul 01 '21 at 18:08
  • @ernest_k I think you meant to say "Not all animals are dogs", because the statement "All animals are not dogs" means no animal is a dog. A not-dog can't be a dog. – Alan Jul 01 '21 at 18:14
  • @Alan I take the two to mean the same thing. But yes, your version is unambiguous. I could be wrong, but my poor English says that *all x are not y != no x is y* :) – ernest_k Jul 01 '21 at 18:20
  • 1
    @ernest_k "not" is a unary operator and binds more tightly, even in English. Likewise with "all". However the form "all x are not y" is unfortunately common when people mean "not all x are y". There the not negates what follows. So it really says "It is not true that all x are y".

    "Not all Luddites are idiots" (some are) is not the same as "All Luddites are not idiots" (none are). Part of the problem is the ambiguity of English: "Cats are wonderful" can mean "all cats are wonderful" or "some cats are wonderful". When they collide with binary thinking, sparks ensue.

    – Alan Jul 01 '21 at 18:37
  • 1
    @Alan You're right in that opting for accuracy, esp. in this context, should be preferred. Agreed. However, I chose to speak the common way, as you observe... As they say, all that glitters is not gold (knowing well that gold itself glitters). 'Not all that glitters is gold' is accurate and should be preferred. 100%. BTW, this language quirk affects other languages too, that I know. – ernest_k Jul 01 '21 at 18:47

2 Answers2

2
Parent parent = new Child();

works because this is inheritance, bigger container (parent type reference variable) can accommodate child object but vise versa is not possible. All properties(methods) of parent are bound to be present in child as part of inheritance so

  Parent parent = new Child(); // works

but child can have additional things(methods/properties) not present in parent and that's why

     Child child = new Parent(); // doesn't work

    Child c = new Child(); vs Parent p = new Child();

this is part of polymorphism here's an example to explain, when Pet pet = new Dog(); and we call pet.makeSound() vrs Dog dog = new Dog(); and we call dog.makeSound()

 import java.util.ArrayList;
 import java.util.List;

abstract class Pet{
 public abstract void makeSound();
    }

 class Cat extends Pet{

     @Override
     public void makeSound() {
         System.out.println("Meow");
     }  
 }

 class Dog extends Pet{

     @Override
     public void makeSound() {
         System.out.println("Woof");
      }

    }

 public class PolymorphismDemo{

     public static void main(String args[]) {
         //Now Pet will show How Polymorphism work in Java
         List<Pet> pets = new ArrayList<Pet>();
         pets.add(new Cat());
         pets.add(new Dog());
 
         //pet variable which is type of Pet behave different based
         //upon whether pet is Cat or Dog
         for(Pet pet : pets){
             pet.makeSound();
         }

     }
 }

Output: Meow Woof

anish sharma
  • 568
  • 3
  • 5
2

Firstly, you must understand what subclassing itself is.

If I have an object, let's say Tree, I may give that object a list of methods like plant(), water().

Then I want to define another class, AppleTree. Well an apple tree still needs to be planted and watered, so instead of copying that code from the Tree class, I'll just subclass it. So AppleTree extends Tree.

This means I can now call Tree's methods directly on an AppleTree object. Then maybe I'll add another method to AppleTree called harvest().

Now let's use this in another class. Maybe I have a class called Orchard that contains all my trees. Let's say I have 10 trees, and 2 of them are AppleTrees. In my orchard, I want to water all of my trees.

I can store all of my trees in an ArrayList like so:

ArrayList<Tree> trees = new ArrayList<Tree>();
for(int i = 0; i < 8; i++)
{
    Tree t = new Tree();
    trees.add(t);
}

for(int i = 0; i < 2; i++)
{
    AppleTree a = new AppleTree();
    trees.add(a);
}

I can then iterate through each of my trees in my ArrayList and call water() on each one.

for(int i = 0; i < trees.size(); i++)
{
    trees.get(i).water();
}

However, now I want to harvest all of my trees, but only 2 of them are AppleTrees and know a harvest() method. So I can't do this:

for(int i = 0; i < trees.size(); i++)
{
    trees.get(i).harvest(); //compiler error
}

This is because my ArrayList holds a set of Tree pointers, which don't know a harvest() method. Not all of my Trees are AppleTrees, and the class signature of Tree does not match the class signature of AppleTree.

All AppleTree objects are Tree objects, so this is ok:

Tree t = new AppleTree();

However, not all Trees are AppleTrees, so this doesn't work:

AppleTree a = new Tree(); //error

It's important to note though, that if I define a Tree this way:

Tree t = new AppleTree();

Even though t contains an AppleTree object, I can't call t.harvest() without casting t to an AppleTree, because to the compiler, it's just a Tree and doesn't know the harvest() method.

So this will fail:

Tree t = new AppleTree();
t.harvest(); //error
Liftoff
  • 24,717
  • 13
  • 66
  • 119