Win a copy of Five Lines of Code this week in the OO, Patterns, UML and Refactoring forum!
  • 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 all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Liutauras Vilda
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • fred rosenberger
  • salvin francis
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Carey Brown

What polymorphic method will be used when an instance is casted?

 
Ranch Hand
Posts: 113
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi everyone,

From one of Enthuware's mock exams:

What will be the result of attempting to compile and run the following program?


I added the following lines myself, because I was curious what would happen:



My expected output from this extra line would be 20, since you're calling a method on an object. The output is 30, however, indicating the original object type (C) is still used. Does this mean that, even when an object is casted to another type (B), calling a method on the reference variable will still invoke the method from the original object type (C), given that the methods exist in both classes B and C? If so, what is the logic behind this?

Thanks again!

Regards,
Shane
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The rules are like this:

Methods are polymorphic. That means that which method will be called is determined at runtime, by looking at the actual type of the object (not the type of the variable that refers to the object). So if you have a C object, then the method in class C is called, no matter if the variable that points to the C object is of type A, B or C. So, o1.m1() and o2.m1() will both return 30, because the variables o1 and o2 both point to the same object which is an instance of class C, so the m1() method in class C will be called.

Member variables are not polymorphic. You cannot override member variables. If you create a member variable with the same name as a member variable in a superclass, then you will have two member variables, and the one in the subclass that hides the one in the superclass. Which one you access, is determined at compile time, by looking at the type of the variable (this is exactly the opposite of how looking up methods works). So, o2.i in line 6 will print 20, because the type of variable o2 is B, and the member variable i in class B has the value 20.
 
author
Posts: 23878
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Shane Jensen wrote:
My expected output from this extra line would be 20, since you're calling a method on an object. The output is 30, however, indicating the original object type (C) is still used. Does this mean that, even when an object is casted to another type (B), calling a method on the reference variable will still invoke the method from the original object type (C), given that the methods exist in both classes B and C? If so, what is the logic behind this?



That is simply how it is supposed to work. When you override a method (with a subclass), the overriddening version (aka. the subclass version) will be called, regardless if you use a superclass reference type to point to it.

Henry
 
Rebecca Wolf
Ranch Hand
Posts: 113
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jesper and Henry,

Thanks for your replies. Is it safe to say that polymorphic methods ignoring any casting that happens? Or is this too blunt?
 
Rebecca Wolf
Ranch Hand
Posts: 113
7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Henry Wong wrote:

Shane Jensen wrote:
My expected output from this extra line would be 20, since you're calling a method on an object. The output is 30, however, indicating the original object type (C) is still used. Does this mean that, even when an object is casted to another type (B), calling a method on the reference variable will still invoke the method from the original object type (C), given that the methods exist in both classes B and C? If so, what is the logic behind this?



That is simply how it is supposed to work. When you override a method, the overridden version will be called, regardless if you use a superclass reference type to point to it.

Henry


That is not always the case, right? What would be the point of overriding a method if the overriden version will be called anyway?
 
Henry Wong
author
Posts: 23878
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Shane Jensen wrote:
That is not always the case, right? What would be the point of overriding a method if the overriden version will be called anyway?



Sorry. Typo. I meant the version in the subclass, aka. the version that overrode the superclass version... fixed in my previous post.

Henry
 
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Shane Jensen wrote:Is it safe to say that polymorphic methods ignoring any casting that happens? Or is this too blunt?


If you focus on runtime behavior, that's true. But please keep in mind that the cast might result in a compiler error (e.g. assume class B defines also a method m2(); the statement o2.m2(); will compile successfully, but ((A)o2).m2(); will result in a compiler error.

Here is a very, very, very important rule: The compiler doesn't execute any code! So every compiler error you get, is because the compiler knows something is wrong without executing any line of code. So the compiler doesn't know and care) about the actual objects, the compiler only knows about the types of the reference variables.

Here are two very simple (and hopefully easy to remember) but very, very, very important rules (which you must know by heart):
  • Which instance variables you can access is determined at compile time based on the reference variable type.
  • Which instance methods you can call/invoke is determined at compile time based on the reference variable type. Which instance method is actually executed is decided at runtime based on the type of the actual object (= polymorphism).


  • Hope it helps!
    Kind regards,
    Roel
     
    Rebecca Wolf
    Ranch Hand
    Posts: 113
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Roel De Nijs wrote:

    Shane Jensen wrote:Is it safe to say that polymorphic methods ignoring any casting that happens? Or is this too blunt?


    If you focus on runtime behavior, that's true. But please keep in mind that the cast might result in a compiler error (e.g. assume class B defines also a method m2(); the statement o2.m2(); will compile successfully, but ((A)o2).m2(); will result in a compiler error.


    Since m2() doesn't exist in A, the method isn't polymorphic, right? So wouldn't my statement still be true, even during compile time (as the compiler would know class A doesn't have method m2() at that point, and thus concludes no polymorphism will be happening)?
     
    Roel De Nijs
    Sheriff
    Posts: 11604
    178
    Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Maybe not really crystal-clear in my previous post, but I stated that your statement was true (correct). Polymorphism happens only at runtime, so when talking about polymorphic behavior you can only focus on runtime behavior The "keep in mind" thing was intended as a good-to-know note (for completeness) and a nice transition to the set of rules I mentioned, not a correction of your statement.
     
    Rebecca Wolf
    Ranch Hand
    Posts: 113
    7
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Roel De Nijs wrote:Maybe not really crystal-clear in my previous post, but I stated that your statement was true (correct). Polymorphism happens only at runtime, so when talking about polymorphic behavior you can only focus on runtime behavior The "keep in mind" thing was intended as a good-to-know note (for completeness) and a nice transition to the set of rules I mentioned, not a correction of your statement.


    Alright! Thanks for the clarification.
     
    Being a smart alec beats the alternative. This tiny ad knows what I'm talking about:
    Thread Boost feature
    https://coderanch.com/t/674455/Thread-Boost-feature
      Bookmark Topic Watch Topic
    • New Topic