• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Method Overriding Problem

 
Greenhorn
Posts: 12
Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What does this exactly mean ?

If a method is overriden but you use a polymorphic (supertype) reference to refer to the subtype object with the overriding method, the compiler assumes you are calling the supertype version of the method. [from the book: Kathy & Bates, the exam watch section]

For the code below:



So, according to the above statement(...the compiler assumes you are calling the supertype version of the method) , shouldn't the output be "Super Animal eats" ? The actual output is rather "Super Cow eats".I am just confused with the above statement. Can someone precisely explain me what does it mean or am I misunderstanding it.
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Achint Verma wrote:So, according to the above statement(...the compiler assumes you are calling the supertype version of the method) , shouldn't the output be "Super Animal eats" ? The actual output is rather "Super Cow eats".I am just confused with the above statement. Can someone precisely explain me what does it mean or am I misunderstanding it.


Kathy Sierra doesn't make many mistakes, so I suspect you've misunderstood the quote.

The fact is that your example will always execute the overridden method if there is one (in fact it's a general rule for Java methods - in C++ parlance they are all 'virtual' unless they're marked final). The fact that the superclass actually implements the method as well does mean that subclasses can leave it out if they want, and the superclass version will act as the "default implementation".

Winston
 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Assuming Kathy did not a mistake, I think what she's trying to do is explain the difference between compile-time interpretation of code by the compiler and runtime execution of code by the JVM. At compile time, the compiler can check type compatibility and assignability. The compiler will accept Line 12 in your listing just fine. However, despite the SuperAnimal reference "sa" being set to point to a subclass, SuperCow, the compiler doesn't really "recognize" that it is SuperCow.eat() that should be called; as far as the compiler is concerned, SuperAnimal.eat() is called. This is because the reference type is SuperAnimal.

The runtime behavior is different. This is where the virtual nature of the eat() method comes out and polymorphism kicks in. It's been quite a while since I've even had to think about this in low-level terms but if I recall correctly, at runtime there is something called a dispatch table which the runtime system uses to figure out the correct version of eat() to execute. The runtime system sees the reference to a SuperAnimal but recognizes that the actual object is a SuperCow. It then goes to the dispatch table, looks up the eat() method for SuperCow (the runtime type) and invokes that method instead of the SuperAnimal.eat().

Hope this helps. (And someone correct me if I'm wrong)
 
Marshal
Posts: 79180
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you are correct, Junilu. There is code which the compiler can check and code which it cannot. In this little program, the runtime type of the object is unknown at compile timeIn this code you must call it like thisThose words (or some of them) should correspond to the class names. The Class.ForName().newInstance() call loads the Dog class, or similar, and creates an object. Obviously the compiler cannot find out in advance whether you are going to say Dog or Mouse or Cat. If you give the name of a non-existent class, the catch give you an Animal object as a default. If you go through the bytecode with . . . you will see that the moo() method calls the noise() method of the Animal class. So that is what the compiler can do with your code: give the compiule‑time type of the superclass (Animal). As you see, when you run it and say Dog, you don’t get “animal noise” as your output.

You will also see a comment like “Did that idiot Campbell really call that method moo()?” Or you might not, but it ought to say that sort of thing
 
Greenhorn
Posts: 13
Android C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:Assuming Kathy did not a mistake, I think what she's trying to do is explain the difference between compile-time interpretation of code by the compiler and runtime execution of code by the JVM. At compile time, the compiler can check type compatibility and assignability. The compiler will accept Line 12 in your listing just fine. However, despite the SuperAnimal reference "sa" being set to point to a subclass, SuperCow, the compiler doesn't really "recognize" that it is SuperCow.eat() that should be called; as far as the compiler is concerned, SuperAnimal.eat() is called. This is because the reference type is SuperAnimal.

The runtime behavior is different. This is where the virtual nature of the eat() method comes out and polymorphism kicks in. It's been quite a while since I've even had to think about this in low-level terms but if I recall correctly, at runtime there is something called a dispatch table which the runtime system uses to figure out the correct version of eat() to execute. The runtime system sees the reference to a SuperAnimal but recognizes that the actual object is a SuperCow. It then goes to the dispatch table, looks up the eat() method for SuperCow (the runtime type) and invokes that method instead of the SuperAnimal.eat().

Hope this helps. (And someone correct me if I'm wrong)




Thanks a ton.
Actually I also came here with a similar problem.

Book: Head first java, 2nd edition.
Topic: Exercise(Mixed message)
Page no: 192

[ a2.m1();
a2.m2();
a2.m3(); ]

I was to create a new topic for this problem. Accidentally stumbled upon this post, as it was looking similar to my query. Then in your reply I checked this link "http://www.javaranch.com/campfire/StoryPoly.jsp" which cleared my doubt. Moreover I learned something new. I wish this to be been explained in the book, but I guess its not possible to push verything in a 700 page book.
Btw this a nice forum, gonna have a good time here.

[PS: Sorry for my bad english, its not my first language]
 
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Any time you have a class that inherits a method from a superclass, you have the
opportunity to override the method (unless, the method is marked final).
The key benefit of overriding is the ability to define behavior that's
specific to a particular subclass type.

.......

class Horse extends Animal {
public void eat() {
System.out.println("Horse eating hay, oats, "
+ "and horse treats");
}
public void buck() { }
}

..........

Animal c = new Horse();
c.buck(); // Can't invoke buck();
// Animal class doesn't have that method

 
hari shankar bhatt
Greenhorn
Posts: 13
Android C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jo Joseph wrote:Any time you have a class that inherits a method from a superclass, you have the
opportunity to override the method (unless, the method is marked final).
The key benefit of overriding is the ability to define behavior that's
specific to a particular subclass type.

.......

class Horse extends Animal {
public void eat() {
System.out.println("Horse eating hay, oats, "
+ "and horse treats");
}
public void buck() { }
}

..........

Animal c = new Horse();
c.buck(); // Can't invoke buck();
// Animal class doesn't have that method



Jo Joseph

Bro can you please elaborate it a little, the stuff you mentioned in the last. I'm confused now.

If I'm guessing it right , this line

animal a = new dog();

is only applicable when we are over-riding( a method previously defined in the parent class).

And in case we invoke a method which is not present animal class, will result in an error.
Please correct me.

Thanks
hari shankar bhatt
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

hari shankar bhatt wrote:If I'm guessing it right...


My advice: Don't guess. Read.

In your specific case: any method that is defined in the class on the left-hand side of the assignment can be called, but when it is, it will use the implementation defined by the class on the right-hand side.

That make it any clearer?

Winston
 
hari shankar bhatt
Greenhorn
Posts: 13
Android C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:
In your specific case: any method that is defined in the class on the left-hand side of the assignment can be called, but when it is, it will use the implementation defined by the class on the right-hand side.

That make it any clearer?

Winston



You made it absolutely clear(transparent ..really). I got it now.

Thank you

hari

 
reply
    Bookmark Topic Watch Topic
  • New Topic