Do both inheritance and polymorphism constitute an IS-A relationship? And is it true that inheritance and “overriding” polymorphism happen in runtime while “overloading” polymorphism occurs in compile time? The reason I ask this is because a lot of forums seem to give conflicting and often confusing answers.
Thanks!
For your first part of the question I think Wikipedia provides a good definition:
Another Wikipedia artile called Polymorphism in object-oriented programming seems to answer your questions very well. The second reference in this article called On Understanding Types, Data Abstraction, and Polymorphism also covers this matters in great detail.
This subtyping feature in Java is achieved, among other means, through inheritance of classes and interfaces. Although the subtyping features of Java may not be evident in terms of inheritance all the time. Take for example the cases of covariance and contravariance with generics. Also, arrays are Serializable and Cloneable although this is not evident anywhere in the type hierarchy. It can also be said that through primitive widening conversion, also numeric types in Java are polymorphic. And operator behave polimorphically depending on their operands.
At any rate, inheritance plays an important role in the implementation of some of this polymorphism.
Overloading vs Overriding
Your second part of the question seems to be about choosing the implementation of a given method. Evidently, if a class overrides a method and you create an instance of that class you want the overriden version of method to be invoked, even if you are accessing the object through a reference of the parent class.
The selection of the right implementation of method is done at runtime as you well pointed out, now the signature of the method to be invoked is decided at compile time. Since overloading is about different methods with the same name and different signature, that is why it is said that overriding method selection happens at compile time.
Overriding Method Selection at Compile Time
The Java Language Specification (JLS) in section 15.12 Method Invocation Expressions explains in detail the process that the compiler follows to choose the right method to invoke.
There, you will notice that this is a compile-time task. The JLS says in subsection 15.12.2:
To verify the compile-time nature of this, you can do the following test.
Declare a class like this and compile it.
Declare a second class that invokes a method of the first one and compile it.
If you invoke the main, the output says
Number.Now, add a second more specific overloaded method to the
ChooseMethodclass, and recompile it (but do not recompile the other class).If you run the main again, the output is still
Number.Basically, because it was decided at compile time. If you recompile the
MethodChooserclass (the one with the main), and run the program again, the output will beInteger.As such, if you want to force the selection of one of the overloaded methods, the type of the arguments must correspond with the type of the parameters at compile time, and not only at run time.
Overriding Method Selection at Run time
Again, the signature of the method is decided at compile time, but the actual implementation is decided at runtime.
Declare a class like this and compile it.
Then declare a second extending class and compile:
And in the MethodChooser class you do:
And if you run it you get the output
Number A, and this is Ok, because the method has not been overriden inChooseMethodBand therefore the implementation being invoked is that ofChooseMethodA.Now, add an overriden method in
MethodChooserB:And recompile just this one, and run the main method again.
Now, you get the output
Number BAs such, the implementation was chosen at runtime, and not recompilation of the
MethodChooserclass was required.