AmitG
AmitG

Reputation: 10543

dynamic polymorphism

class Test {
    public static void main(String[] args) {
        Animal a = new Dog();
        Dog d = new Dog();

        d.makeNoise();  // output "Sub"
        a.makeNoise();  // output "Sub"  then what is use of calling this. why not call d.makeNoise() only.

    }
}

abstract class Animal {
    public void makeNoise() {
        System.out.println("Super");
    }
}

class Dog extends Animal {
    @Override
    public void makeNoise() {
        System.out.println("Sub");
    }
}

We had 15 minutes discussion over this topic(15 minutes is too long I guess) I explained interviewer about how dynamic polymorphism will be achieved with the help of a.makeNoise(); but still she was saying both are giving same output.
a.makeNoise(); output "Sub" then what is use of calling this. why not call d.makeNoise() only
I went to interface also but still question was if subclass reference is giving same output then why to use superclass reference.

Interviewer question was, what difference a.makeNoise(); makes? why not call d.makeNoise(); only when both are giving same output?

What could be the possible correct answer?

Upvotes: 0

Views: 997

Answers (8)

ashik alias
ashik alias

Reputation: 9

consider there are 3 classes

  1. animal
  2. dog
  3. cat cat and dog are sub classes of animal.

class Test {
    public static void main(String[] args) {
        Animal a = new Animal();
       
    int user_input=userinput();  //returns 1 for cat and 2for dog
    switch(user_input)
    {
    case 1:Animal d=new Cat();
    break;
    case 2: Animal d=new Dog();
    break;
    }
        d.makeNoise();  // output "Bark"/"meow"  as per user input(dynamic linking)
        a.makeNoise();  // output "Squawk"  - a is an animal that squawks
    }
    } 
    class Animal {
    public void makeNoise() {
        System.out.println("Squawk");
    }
    } 
    class Cat extends Animal {
    @Override
    public void makeNoise() {
        System.out.println("meow");
    }
    }
    class Dog extends Animal {
    @Override
    public void makeNoise() {
        System.out.println("Bark");
    }
    }

Upvotes: 1

Harshil
Harshil

Reputation: 1300

Animal a = new Dog();

a is a a reference of type Animal but it refers to the object of type Dog.

Here Dog overrides makeNoise() method of Animal class.

class Animal {
    public void makeNoise() {
        System.out.println("Squawk");
    }
}

class Dog extends Animal {
    @Override
    public void makeNoise() {
        System.out.println("Bark");
    }
}

Since object is of Dog class JVM will bind Dog class' makeNoise() method to the object and binding will be done at runtime.

so the Output of

a.makeNoise();

will be

sub

Upvotes: 0

varma
varma

Reputation: 11

i will give one general ex:- personA has one bank account he has all permissions on that account(withdraw,deposit,loanetc). personB wants to deposit money into personA account in this time he wants to access personA's account but we have to provide deposit permissions only.

 class perosnB
{
 public void deposit()
{ 
................
 } 
 } 
class personA extends personB
{  
public void deposit()
{
......
}
public void withdraw() 
{ 
...... 
} 
} 
personA p=new personB(); 
PersonB p2=new personB(); 

by using p object we can access only withdraw method. by using p2 we can access deposit also. weather personA class is abstract or not. if personA is abstract class creating object for personA class is not possible( personA p=new personA()) . personA p=new personB() is possible.

Upvotes: 0

Joe2013
Joe2013

Reputation: 997

class Account {
    public static void main(String[] args) {
        Animal a = new Dog();
        Dog d = new Dog();
        d.makeNoise();
        a.makeNoise();
        a = new Cat();
        a.makeNoise();
    }
}

abstract class Animal {
    public void makeNoise() {
        System.out.println("Super");
    }
}

class Dog extends Animal {
    public void makeNoise() {
        System.out.println("Sub");
    }
}

class Cat extends Animal {

}

See the above modified example and the observations

  1. We have an abstract class Animal with an implementation for makeNoise (let me say default implementation here)
  2. We have a Dog class which is of Type animal but has a customized makeNoise methods
  3. We have a Cat Class which is of Type animal but has no customized makeNoise methods. it uses default makeNoise of Animal type.
  4. if I use Animal a = new Dog() and a.makeNoise(), then I can remove my makenoise method from Dog class whenever I wish with no changes to any other class. It will still compile and execute without any error.
  5. if I use Dog d = new Dog() and d.makeNoise(), then I cannot remove my makenoise method from Dog class whenever I wish. if I do, I also need to change the main class for the application to compile.

Upvotes: 0

Tadas S
Tadas S

Reputation: 1963

Your simplified example does not present the case well enough.

Collection<Animal> caged = getCagedAnimals();
for (Animal a : caged)
  a.makeNoise();

As there are many types of animals (classes), each makes a different noise. We do not need any typecasting to obtain different behavior, so to say. Imagine the horrors which would happen if we would want each animal to make a noise without polymorphism:

for (Animal a : caged) {
  if (a instanceof Dog)
    ((Dog)a).woof(); // or, ((Dog)a).makeNoise()
  else if (a instanceof Cat)
    ((Cat)a).meow(); // or, ((Cat)a).makeNoise()
  else {...}
}

Let us have an object of type T. We are trying to invoke toString() (defined by Object class) Dynamic method invocation proceeds as follows (actually, a virtual method table is used):

C = T
do
  if (C defines toString()) {
    call T.toString()
    break
  }
  C = superclass of C
while (C != null)
throw new NoSuchMethodError();

Now, if we have

Object obj = new T();

and we call

obj.toString();

we are actually calling toString() of class T.

Upvotes: 1

Klas Lindb&#228;ck
Klas Lindb&#228;ck

Reputation: 33273

The example below illustrates dynamic polymorphism. Both a and d are declared to be Animals, but d is actually a dog.

Notice that when I call makeNoise on the Animal d, java will know that d is actually a dog and not just any animal.

class Test {
    public static void main(String[] args) {
        Animal a = new Animal();
        Animal d = new Dog();

        d.makeNoise();  // output "Bark"  - d is an animal that barks
        a.makeNoise();  // output "Squawk"  - a is an animal that squawks

    }
}

class Animal {
    public void makeNoise() {
        System.out.println("Squawk");
    }
}

class Dog extends Animal {
    @Override
    public void makeNoise() {
        System.out.println("Bark");
    }
}

Upvotes: 2

sp00m
sp00m

Reputation: 48807

Animal a = new Dog();    // this animal is a dog
Dog d = new Dog();       // this dog is a dog

A dog is a dog, however you declared it.

a.getClass() equals d.getClass() equals Dog.class.

On the other hand:

Animal a = new Animal(); // this animal is an animal
a.makeNoise();           // prints "Super"

Upvotes: 2

Sudhanshu Umalkar
Sudhanshu Umalkar

Reputation: 4202

This is the reason-

Animal a = new Dog();

Animal is dog so noise would be same :)

If create another animal, say Cat, with that method, and point animal to Cat, you should get a different noise.

Upvotes: 1

Related Questions