Caroline Yi
Caroline Yi

Reputation: 213

Why can this object access methods of it's parent class?

This question is taken from an AP Computer Science practice test.

public class Bird
{
    public void act()
    {
        System.out.print("fly"); 
        makeNoise(); 
    }
    public void makeNoise()
    {
        System.out.print("chirp"); 
    }
}

public class Dove extends Bird
{
    public void act()
    {
        super.act(); 
        System.out.print("waddle"); 
    }
    public void makeNoise()
    {
        super.makeNoise(); 
        System.out.print("coo"); 
    }
}

Suppose the following declaration appears in a class other than Bird or Dove:

Bird pigeon = new Dove(); 

What is printed as a result of the call pigeon.act()?

I thought the answer would be "fly chirp", but the textbook says that the answer is "fly chirp coo waddle". I thought that 'pigeon' could only access methods available in Bird? I was under the impression that, if the user wanted to access methods in Dove, 'pigeon' would have to be cast to Dove.

Would Bird pigeon = new Bird(); give the same output? How about Dove pigeon = new Dove();?

Upvotes: 5

Views: 305

Answers (4)

nits.kk
nits.kk

Reputation: 5316

From your question "I thought that 'pigeon' could only access methods available in Bird? I was under the impression that, if the user wanted to access methods in Dove, 'pigeon' would have to be cast to Dove." This is actually true.

Lets try to find the mssing link in the understanding.

  1. When we have code like Bird pigeon = new Dove(); where Dove extends Bird we have actual object of Dove and reference type is of Bird. As the object is of Dove so it has the methods, both inherited from super class as well as the ones which are added.

  2. Another important point is all the overriden methods have only one instance. Its Overriden meaning the behavior of the same method has been modified, its not an additional separate method. There is only one copy of inherited method not both. Its the overloaded methods which are separate, just the names are same but signature is different. This is the reason you get the behaviour of Dove when you invoke any overriden method.

  3. This one is simple super , using it a sub class can access the accessible (visible) entities (instance properties and methods) of its super class. If a sub class uses super keyword to invoke a method then its the method of the parent class which gets invoked. But again this can be considered that the author of the sub class did it intentionally. Once the class is written and Objects of such class is created then on the object using . (dot operator) users can only invoke whats there in the object. If any method has used super keyword its part of the behavior of the object. Users of the Sub class object can not invoke behavior of the parent class method if its overridden in sub class.

  4. Lastly yes if you wish to invoke any additional method of Dove (Sub class ) using a reference of Bird (Super class) then you need to cast it to Dove.

Upvotes: 1

GhostCat
GhostCat

Reputation: 140427

What you experience here is polymorphism in action. And instead of answering your various questions directly; I will simply explain the case you are observing.

You call act() on an instance of Dove; that causes a call to super; printing "fly".

That super method then calls makeNoise() ... on "itself". But as said: "itself" is a Dove object; thus you get the Dove noise! "coo"!

Then the Dove implementation ends; and prints "waddle".

The essence is: the exact version of a method that is invoked is determined at runtime and it only depends on the exact type of the object the method is invoked on.

The above gives you all the information you need to answer your other questions yourself. In that sense: don't request answers; ask for explanations; and use those to solve the puzzle yourself!

Upvotes: 2

Harmlezz
Harmlezz

Reputation: 8068

  • the class Dove does override the methods act and makeNoise of class Bird. Overriding means changing the behavior of a method visible to the sub-class, (in your case Dove). Methods are visible to a sub-class if they have a public or protected access modifier or if they have a package private access modifier and the sub-class belongs to the same package as the super-class does.
  • pigeon is an instance of Dove.
  • calling pigeon.act() results in calling Dove.act.
  • Dove.act calls super.act which is Bird.act.
  • Bird.act prints fly and calls makeNoise on pigeon resulting in calling Dove.makeNoise.
  • Dove.makeNoise calls super.makeNoise which is Bird.makeNoise.
  • Bird.makeNoise print chirp.
  • Dove.makeNoise prints coo after calling super.makeNoice

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726529

Long story short, when you access act method of pigeon, its override from Dove is called.

I thought that 'pigeon' could only access methods available in Bird?

That is certainly true, at least, for situations when no casting is applied. However, method act is available on the class Bird, the statically known type of pigeon, so the call compiles fine.

However, accessing methods is only about being able to call them. What methods do when you call them is decided at runtime based on the dynamic type of pigeon. This is where method overriding comes into play, because Dove overrides Bird's methods, but in addition it also calls Bird's methods. That is why the code hits all four printouts.

Would Bird pigeon = new Bird(); give the same output?

No, the output would be different, because in this case both dynamic and static types of pigeon would be the same, i.e. Bird, so only Bird's implementations would be invoked.

Upvotes: 3

Related Questions