Meaningless Drivel is fun!*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Polymorphism Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Polymorphism" Watch "Polymorphism" New topic
Author

Polymorphism

B Gallagher
Greenhorn

Joined: Mar 18, 2004
Posts: 2
OK, I am a little confused about polymorphism. Can someone explain to me what's going on here?
Given:

This gives me "Horse eating hay ":

But this does not compile:

So in the first case, "the compiler looks at the actual object type to determine which method is invoked", but in the second case, it (apparently) does not. Why? Is it because in both cases I am declaring an Animal reference, and the eat method that takes a string is not in that class? If so, then the phrase "the compiler looks at the actual object type" seems a bit misleading to me, because in both cases it is actually looking at the reference type.
Edited by Corey McGlone: Added CODE Tags
[ March 31, 2004: Message edited by: Corey McGlone ]
Charlie Goth
Ranch Hand

Joined: Feb 26, 2004
Posts: 60
Animal ah2 = new Horse();
ah2.eat("Carrots");
This doesn't work because there is no method eat(String s) in Animal, it only works on references of type Horse. There is an eat() method though (in Animal) so that works fine.
Charlie


SCJP (77%)
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Ok, I see where you're getting confused. First of all, realize that the compiler can't look at the type of object that a variable references - it doesn't know because that isn't determined until run-time.
We have the notion of compile-time types and run-time types. A compile-time type is the type we have declared for a variable. In your example, ah and ah2 both have compile-time types of Animal. A run-time type is the type of an object that a variable references at a given point in time during execution. In your example, ah and ah2 both have run-time types of Horse.
So, what does this all mean?
Well, the compiler can only check one type - you guessed it, the compile-time type. Therefore, the compiler knows that ah and ah2 reference some type of Animal. That might be an Animal and it might be a Horse, but the compiler doesn't know for sure.
As the compiler doesn't know what it really references, it has to err on the side of caution. ah.eat() works just fine because Animal has an eat() method that takes no arguments. Therefore, the compiler knows that this method invocation has a valid target (it might be overridden, but the compiler doesn't know and doesn't care - all it cares about is the existence of a valid method to invoke).
When you invoke ah2.eat("Carrots"), however, the compiler is put in quite a bind. The compiler knows that ah2 has a compile-time type of Animal. That means that it can reference an Animal or any subclass on Animal. However, Animal doesn't have a method named eat that takes a String as a parameter. If the run-time type were to be Horse (which, in this case, it is), the method invocation would work fine. But, like I said earlier, the compiler knows nothing about what ah2's run-time is. Because the compiler knows that ah2 might reference an Animal object, it's possible that there will be no valid method to invoke. That's a big no-no for the compiler, so it complains.
I hope that helps,
Corey


SCJP Tipline, etc.
B Gallagher
Greenhorn

Joined: Mar 18, 2004
Posts: 2
So -- if I understand correctly -- adding a new eat(String) method to the Animal class would allow that code to compile, but it would *run* the eat(String) method from Horse!
Ray Stojonic
Ranch Hand

Joined: Aug 08, 2003
Posts: 326
The compiler does indeed look at the reference type, which is why Animal.eat( String ) won't compile.
The the proper method is called on the appropriate object during runtime via dynamic method lookup, ie:
Animal a = new Horse();
a.eat();
o/p : Horse eating hay
During compilation, the compiler says "okay, call eat() on this Animal object"
During runtime, the JVM says "hey, this is a Horse, call Horse.eat()", which is the cool part of polymorphism.
You'll have to fill in the missing parts in this example, but here it is:

o/p:
Horse eating hay
Chicken eating feed
Pig eating apples
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Originally posted by B Gallagher:
So -- if I understand correctly -- adding a new eat(String) method to the Animal class would allow that code to compile, but it would *run* the eat(String) method from Horse!

Absolutely!
Brian Albin
Greenhorn

Joined: Mar 02, 2004
Posts: 24
One quick question ...

I can understand upcasting the reference to an Animal when storing objects of type Horse, Chicken, Pig in an array.
Animal[ ] = new { ... };
One array can hold various types of animals.

But what advantage is their in saying ...
Animal ah = new Horse( );
It would seem that ...
Horse ah = new Horse( );
is a better description of what is actually taking place in code.
Brian Albin
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Originally posted by Brian Albin:
But what advantage is their in saying ...
Animal ah = new Horse( );
It would seem that ...
Horse ah = new Horse( );
is a better description of what is actually taking place in code.

You're right, Brian. It would seem better to have the compile-time type be Horse, in this case. However, this is a somewhat contrived example derived to show the function of polymorphism. In real life, ploymorphism really shines when we don't know, ahead of time, what type of object we're really dealing with.
Corey
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Polymorphism