• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Doubt with overridden methods

 
Alfonso Sanz
Ranch Hand
Posts: 42
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everybody!!

I'm new here. I'm studying for OCA 8 exam and I have found one doubt.

For the code:



I don't understand why it outputs: "Reptile laying eggs" instead of "Lizard..."

According what I have read is the object type who determines the method. Then.. Since object is Lizard, why invokes Reptile method?


Thanks in advance and sorry for my ignorance.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Alfonso Saenz,

First of all, a warm welcome to CodeRanch!

Alfonso Saenz wrote:According what I have read is the object type who determines the method. Then.. Since object is Lizard, why invokes Reptile method?

It's a trick question Only methods which are inherited can be overridden. And private methods are never inherited and thus can never be overridden. Repeat after me: private methods are never inherited and thus can never be overridden! So the layEggs() method in class Lizard seems to be overriding the layEggs() method in class Reptile, but that's not true. In fact, because the layEggs() method in class Reptile is private, class Lizard doesn't know class Reptile has a layEggs() method. And if you don't know about a method, you definitely can't override it.
Because the type of the reference variable reptile is Reptile and the layEggs() method in class Reptile is not overridden (for the aforementioned reason), the layEggs() method in class Reptile is simply executed (no polymorphism is happening here). If you remove the private access modifier from the layEggs() method in class Reptile, you'll get the output you were expecting.

Alfonso Saenz wrote:Thanks in advance and sorry for my ignorance.

No need to apologize! We are all here to learn and improve our (Java) knowledge.

Hope it helps!
Kind regards,
Roel
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alfonso Saenz wrote:According what I have read is the object type who determines the method. Then.. Since object is Lizard, why invokes Reptile method?

In this thread you'll find an excellent explanation as well about a similar code snippet. Definitely worth reading!
 
Alfonso Sanz
Ranch Hand
Posts: 42
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First of all: thank you so much for the welcome and the answer.

I knew the method was not overridden, but I thought that as a hidden method, was the lizard's which is invoked.

Thanks again.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alfonso Saenz wrote:I knew the method was not overridden



Alfonso Saenz wrote:but I thought that as a hidden method, was the lizard's which is invoked.

The type of the actual object (to which a reference variable is refering) only matters if a method is overridden and at runtime the JVM needs to decide which method will be executed (= polymorphism). In all other cases, which method (or field) will be invoked (or accessed) is determined based on the reference variable type.
 
Alfonso Sanz
Ranch Hand
Posts: 42
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
now is clear. Thank you Roel De Nijs!!
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let's see if everything is clear and you have understood with one of my famous pop quizzes

What's the output of this code snippet?
 
Alfonso Sanz
Ranch Hand
Posts: 42
3
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let's see...

in this case, method eat() in Animal is public, so... it is overridden in Lion with same signature and return type.
In this case both objects are Lion() and both will print the output given by Lion's method.

There is another issue with Exceptions. NotHungryException is not declared or treated in main()

It should be:



or:


 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alfonso Saenz wrote:In this case both objects are Lion() and both will print the output given by Lion's method.

There is another issue with Exceptions. NotHungryException is not declared or treated in main()

You are correct! Have a cow for not getting fooled by my contrived code snippet

And this code snippet illustrates again that the reference variable determines which method can be invoked. So although reference variable a refers to a Lion object and we know that a lion is always hungry and will never throw a NotHungryException, the compiler only sees the reference variable type (which is Animal) and thus only these methods can be invoked. Because the eat() method might throw a checked exception, the compiler forces you to handle or declare this checked exception. And if you don't meet this requirement (with the current code snippet), you'll get a compiler error.
If the NotHungryException is handled or declared (using one of your proposed changes), the code will compile and "lion always hungry!" will be printed twice.

Hope it helps!
Kind regards,
Roel
 
Alfonso Sanz
Ranch Hand
Posts: 42
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The explanation clarifies even more the topic. Thanks, but... what can I do with a cow??
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alfonso Saenz wrote:Thanks, but... what can I do with a cow??

If you take good care of your cattle, you can milk her twice a day and enjoy some fresh milk

Just like on Facebook, you can the post(s) which you liked. So other ranchers will see immediately which are the "starred" posts. But for awesome, very helpful,... posts someone can award you a cow (that's much better than +1). If you would like to know more about the ranch cows, you can read the Ranch Cows article.
 
Vani Dasu
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Roel,

As you mentioned that the reference variable determines the method to be invoked, you mean in


'a' being a reference of Animal goes to eat() present in the Animal class, then checks on the access specifiers - which is public hence it knows it can be inherited. Now as 'a' points to the object of Lion class and eat() can be inherited, goes and checks in Lion class. JVM finds the eat() in Lion and hence executes "Lion is always hungry".

Hope i am right.
If my understanding is right, what would happen if 'a' after realizing that eat() can be inherited, checks in Lion but doesn't find any eat() then it comes back to Animal and executes eat() of Animal?
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Vani Dasu,

First of all, a warm welcome to CodeRanch!

Vani Dasu wrote:'a' being a reference of Animal goes to eat() present in the Animal class, then checks on the access specifiers - which is public hence it knows it can be inherited. Now as 'a' points to the object of Lion class and eat() can be inherited, goes and checks in Lion class. JVM finds the eat() in Lion and hence executes "Lion is always hungry".

Hope i am right.

Yes, you are! And there's another implication as well. Although the actual object denoted by reference variable a is Lion and thus you know (checked) NotHungryException will never be thrown, you still have to handle-or-declare this exception. And that's because the compiler only knows about the type of the reference variable a, which is Animal and its eat() method has the (checked) NotHungryException in its throws clause.

Vani Dasu wrote:If my understanding is right, what would happen if 'a' after realizing that eat() can be inherited, checks in Lion but doesn't find any eat() then it comes back to Animal and executes eat() of Animal?

Yes, that's exactly what will happen. In this post and the next one, I have given a detailed explanation about the process to determine which method should be invoked for two similar scenarios (one with a private method and another one with an overridden method).

Hope it helps!
Kind regards,
Roel
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic