This question already has answers here:
What is the main difference between Inheritance and Polymorphism?
(18 answers)
Closed 5 years ago.
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:
In object-oriented programming, subtype polymorphism or inclusion
polymorphism is a concept in type theory wherein a name may denote
instances of many different classes as long as they are related by
some common super class. Inclusion polymorphism is generally
supported through subtyping, i.e., objects of different types are
entirely substitutable for objects of another type (their base
type(s)) and thus can be handled via a common interface.
Alternatively, inclusion polymorphism may be achieved through type
coercion, also known as type casting.
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:
This step uses the name of the method and the types of the argument expressions
to locate methods that are both accessible and applicable
There may be more than one such method, in which case the most specific one is chosen.
To verify the compile-time nature of this, you can do the following test.
Declare a class like this and compile it.
public class ChooseMethod {
public void doSomething(Number n){
System.out.println("Number");
}
}
Declare a second class that invokes a method of the first one and compile it.
public class MethodChooser {
public static void main(String[] args) {
ChooseMethod m = new ChooseMethod();
m.doSomething(10);
}
}
If you invoke the main, the output says Number.
Now, add a second more specific overloaded method to the ChooseMethod class, and recompile it (but do not recompile the other class).
public void doSomething(Integer i) {
System.out.println("Integer");
}
If you run the main again, the output is still Number.
Basically, because it was decided at compile time. If you recompile the MethodChooser class (the one with the main), and run the program again, the output will be Integer.
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.
public class ChooseMethodA {
public void doSomething(Number n){
System.out.println("Number A");
}
}
Then declare a second extending class and compile:
public class ChooseMethodB extends ChooseMethodA { }
And in the MethodChooser class you do:
public class MethodChooser {
public static void main(String[] args) {
ChooseMethodA m = new ChooseMethodB();
m.doSomething(10);
}
}
And if you run it you get the output Number A, and this is Ok, because the method has not been overriden in ChooseMethodB and therefore the implementation being invoked is that of ChooseMethodA.
Now, add an overriden method in MethodChooserB:
public void doSomething(Number n){
System.out.println("Number B");
}
And recompile just this one, and run the main method again.
Now, you get the output Number B
As such, the implementation was chosen at runtime, and not recompilation of the MethodChooser class was required.
Polymorphism: Ability of different objects to receive same message and respond to differently.
Inheritance a way to achieve it, but not necessary. See Duck Typing
Overloading of a method is 'compile time syntax helper'- as every method gets a unique signature after compilation. Not really anything to do with polymorphism.
Polymorphism is an effect of inheritance. It can only happen in classes that extend one another.
Polymorphism does happen at runtime; I've never heard of "overloading polymorphism".
Inheritance happens at compile time, the moment you write:
class A extends B
{
}
I think you're right.
Polymorphism considers the runtime type of the object to decide wich method execute and the choice of which overloaded method to call is not dinamically decided at runtime, it depends on the types of the parameters at compilation time.
Only inheritance constitute an IS-A relationship. polymorphism has nothing to do with it.
"overloading" is example of polymorphism. You can learn more about run-time and compile-time polymorphism here
• Inheritance defines parent-child relationship between two classes, polymorphism takes advantage of that relationship to add dynamic behavior in your code.
• Inheritance encourages code reusability by allowing child class to inherit behavior from the parent class. On the other hand, Polymorphism allows the child to redefine already defined behavior inside the parent class. Without Polymorphism, it's not possible for a child to execute its own behavior while represented by a Parent reference variable, but with Polymorphism it can be done.
• Java doesn't allow multiple inheritance of classes but allows multiple inheritance of Interface, which is actually required to implement Polymorphism. For example, a class can be Runnable, Comparator and Serializable at the same time because all three are interfaces. This makes them pass around in code e.g. you can pass an instance of this class to a method which accepts Serializable, or to Collections.sort() which accepts a Comparator.
• Both Polymorphism and Inheritance allow Object-oriented programs to evolve. For example, by using Inheritance you can define new user types in an Authentication System and by using Polymorphism you can take advantage of the already written authentication code. Since, Inheritance guarantees minimum base class behavior, a method depending upon super class or super interface can still accept an object of the base class and can authenticate it.
Related
Before I ask my question, let me to explain my understanding and opinion.
By only Overriding we can't achieve polymorphism unless there is upcasting. And as it can only seen at runtime people might have named it as Run time ploymorphism. (I have no objection to call polymorphism as Run Time Polymorphism)
I have objection to call method overloading as compile time polymorphism or polymorphism.
I agree that method overloading is static binding (compile time binding), but I can't see polymorphism in that.
According to the javadoc, there is only polymorphism. There is no compile time or run time polymorphism.
According to javadoc in a section called Defining Methods, it explains Overloading of Methods. But there is nothing about compile time polymorphism.
According to me:
If you put polymorphism in to category of Run time polymorphism, you can only see "compile time polymorphism" when you change your JDK version:
If you switch from a higher JDK version higher to a lower one, you will start seeing compilation errors. The same code behaving differently during compilation time, eg: lambda expression, diamond operator, string in switch case, generics etc.
Let me elaborate my opinion, my prediction about how run time polymorphism and compile time polymorphism came to blogs/tutorials:
Conversation1
Developer 1: Hey I read about polymorphism today. If you do coding to interface, you can achieve polymorphism. writing codes not tightly coupling to a class but instead writing it to interface by making loose coupling, calling a superclass method or interface method actually invokes method of subclass depending on instance passed.
Developer 2: Sorry, I didn't get you.
Developer 1: It's simple at run time which object instance you will pass, that instance method will be executed.
Developer 2: Ohh! Run Time. I got it.
Developer 1: Yes same piece of code, but at Run Time passed instances are different.
Developer 2: **Run Time! Okay, I got it.
Conversation2
Developer 2: Hey yesterday I've met Developer1, he was telling about some run-time polymorphism. By overriding methods in a sub-class we can achieve it.
Developer 3: Run time polymorphism by overriding methods? Then what is oveloading? Compile time polymorphism?
Developer 2: How do you say overloading as compile time polymorphism?
Developer 3: Because it is decided at compile time only.
Developer 2: Silent!
Polymorphism and coding to interface best example is java.sql:
java.sql.Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
java.sql.Statement stmt = conn.createStatement();
java.sql.ResultSet rs = stmt.executeQuery(sql);
The same piece of code behaves differently based on the Driver registered. This means, if we register the Mysql driver, due to polymorphism this code executes methods of mysql instances. I.e. it executes overridden methods. If you register the Oracle driver, it works for Oracle, and so on.
Above we found same code behaving differently.
Now can anyone show me same code behaving differently in compile time. Or in other words show me add(3,4) method bounded to different methods (other signatured methods) during compile time?
According to javadoc,
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures.
The method will be executed depending on signature matched. Having same name for methods does not mean there is a polymorphism, because calling methods signature is different:
Queestion1: If you won't change calling method signature will it call different method other than method for which signature has matched? In any condition will it behave differently?
Let's look at Method overloading:
public void add(int a, int b)
{
System.out.println(a+b);
}
public void add(int a, int b, int c)
{
System.out.println(a+b+c);
}
public static void main(String[] args)
{
add(3,4);
add(3,4,5);
}
Question 1: If method overloading is polymorphism, Which piece of code behaving differently in above block of code? Where is polymorphism here?
Question 2: Method invocation add(3,4); on what scenario it shows ploymorphism, unless it is modified to add(3,4,5)?
EDIT
#FutureVisitor since this thread found no answers in favor of method overloading as a type of polymorphism(Even after a month of question being asked), without any justification accepting answer in favor of Method overloading is not a polymorphism, if any answer points problem in my argument of method overloading is not polymorphism will be accepted and supported their views.
In the Java world, polymorphism means polymorphism between classes. I.e. refering possibly multiple child classes with their common parent. In Java, there is no polymorphism between methods.
void add(int a, int b) and void add(int a, int b, int c) are entirely different methods in the Java syntax. It shouldn't be so - for example, in C++, you can cast them to each other -, but it is so in Java.
The key concept to understand here is the method signature. The method signature defines in a language, what identifies the induvidual methods. (For example, beside a void add(int a, int b);, you simply can't declare an int add(int a, int b); method - the return value is not a part of the method signature in Java, thus the compiler would interpret it as a method re-definition.)
People say
overriding is run time polymorphism and
overloading is compile time polymorphism.
Both are wrong.
Only Overriding is not polymorphism. But overriding helps to achieve polymorphism. If there is no upcasting you can't achieve polymorphism.
Overloading is a concept where method-name along with argument signature is used to bind method call to method body and it can be predicted during compile time only. But this is nowhere related to polymorphism. There is NO behavioral change that can be found in the case of method overloading. Either you compile today or compile after one year behavioral change can only be found if you change calling method signature i.e, only if you modify code to say add(3,4); to add(3,4,5); and hence method overloading is not polymorphism.
java.lang.Class defines multiple methods which only apply to a certain type of class, e.g.:
getComponentType: Only relevant for arrays
getEnumConstants: Only relevant for enums
So why is there, for example, no ArrayClass which defines the getComponentType method instead?
This appears to be more or less a design choice. Since i did not design this language, i cannot answer it with certainty, but i'll try to explain potential reasons for this.
So why is there for example no ArrayClass which defines the getComponentType method instead?
The trick to understanding this is, that the java.lang.Class class is not a direct equivalent to the class you are coding. This specific class is only used to represent the created class at runtime (for example: for the use of reflections).
As from the Java-Doc of the Class (here from Java 7):
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
You are writing custom classes, if you write your code, which means that your created code is the class. If you create a class called the ArrayClass, this is your class. The java.lang.Class class is then only usable at runtime to analyze the class of this specific Object.
For the design in Java, two more layers of complication are added.
First: You can analyze every object, which is a subtype of java.lang.Object. The method getClass is defined here. This means that you are able to introspect any object for any specific detail. If the specific type of the Object is not an enum for example, the class returns null upon calling getEnumConstants. If you had specific sub-types of the java.lang.Class, you would have to cast the instance before introspecting it, which would make it more annoying to work with.
Second: The java.lang.Class object, representing your type is created lazy, within the ClassLoader. Upon referenzing a specific type, the ClassLoader checks whether or not the Class is already loaded and if not, loads it. It then creates the java.lang.Class-Objects, which represents this specific Type. This class-object can then be used, to create instances of your type.
If the java language had different subtypes for the java.lang.Class, the ClassLoader would have to instantiate the correct subtype of the Class, corresponding to what would be needed. If you where able to create custom subtypes of the java.lang.Class, this would get out of hand quickly. How is the ClassLoader supposed to know which Class-instance is connected to your Type? Would you have to write specific Class-instances and somehow mark your created type to use that Class-instance? You could imagine something like this:
public class MyType extends ... implements ... type MyClassInstance
But then, how do you fill up custom fields within your custom java.lang.Class instance? Those complications may be the reason, that the java.lang.Class has a generic type, representing the connected Type. Event though there are a million possible solutions to those complications, there still might be an argument to be made for usability and robustness.
As Oracle point out in there Design Goals of the Java Programming Language:
The system that emerged to meet these needs is simple, so it can be easily programmed by most developers; familiar, so that current developers can easily learn the Java programming language; ...
As much as one would love to see something like this within the language, this feature would make it way more complicated, since it would allow developers to change the behavior of the newInstance method for example. You could introduce an Exception within this Method and one might think, the constructor threw an Exception, even though it did not. This goes into the same (or a similar) direction as Why doesn't Java offer operator overloading?, with that, you are essentially overriding the new keyword.
The Class currently is final (likely because it is a core language construct). This prohibits subtypes of java.lang.Class. If the class should receive subtypes, it has to loose final which means anyone could override any specific detail for a class. Calling getClass could result in any unknown type, that could do anything.
With that, we now only have specific subtypes of classes, we still cannot access them. To do this, we have to do one of the following:
Either add a generic type to the Object like this (i don't want to start a debate about super or extends, this is just an example):
public class Object<T extends Class> {
public final native T getClass();
}
This is required because we want to have certain classes connected to certain objects. With this however, we are not specifying how to instantiate the class. Normally a class is instantiated through the ClassLoader. Again from the JavaDoc:
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
This would no longer be viable, except we require certain aspects like a private constructor. Also, we had to provide every custom Class as native C++ code.
The other possibility would be, to define the getClass method in implementations something like this (this code has different generic based issues, but again, just an example):
public class Object {
public <T extends Class<?>> T getClass() {...}
}
public class MyType {
public MyClass getClass() { return new MyClass(); }
}
Which would open the door to more complicated issues introduced earlier. You could now do work in here, that you are not supposed to do. Imagine a InvocationHandler for example. The other issue with this is that now the developer has the freedom to decide whether or not a Class is instantiated only once or multiple times, which would break for example the Class-Based-Programming and of course some aspects of the Java-Language.
Even though i cannot answer with certainty, i hope this helped a bit.
If I declare that my object implements an interface, but fail to implement those methods, when I compile my code, I get a compiler error. How does the java compiler know that I haven't implemented all of the methods of an interface?
How does the java compiler know that I haven't implemented all of the methods of an interface?
It knows all methods that your class has implemented because it has found and analyzed them during the compilation.
It knows all of the methods that were defined in all of the superclasses and interfaces of your class because:
it has either just compiled their source code, or loaded their ".class" files, and
it has analysed the interfaces / classes and figured out which methods need to be implemented by your class.
Then it compares the two sets of methods. (Note that the methods don't need to be exactly the same. For example, the actual method could return a subtype of the return type of the method in the interface. The set comparison needs to take account of that.)
(Actually, that is just one approach to doing this check. An actual Java compiler might do the checking a bit differently.)
Public class John {
public void setValue(){
this.value = 0;
}
public void setValue(int v){
this.value = v;
}
Now potentially how would i call these two methods??
John j = new John();
j.setValueO();
j.setValue(10);
Correct me if i am wrong.
Is function overloading a concept of polymorphism? If not, under which OOP branch does this come.
Encapsulation means Hiding the information and Abstraction means Hiding the implantation details. So when i do overload a method, do i carry anything on these two above... {Abstraction and Encpsulation}
Is Overloading compile time or runtime? Why do they call this for overloading and overriding?
Yes you are right, expect the typo which you have made?
Is function overloading a concept of polymorphism? If not, under
which OOP branch does this come.
Well speaking from historical point of view, it does come but still many argue that its not a form of polymorphism.
Overloading
The method functions differently based on the arguements.
Overriding
The method functions differently based on which class was used to instainate it.The method bark could sound differently for Class CAT and Class DOG.
Encapsulation means Hiding the information and Abstraction means
Hiding the implantation details. So when i do overload a method, do i
carry anything on these two above... {Abstraction and Encpsulation}
Nope. May be someone can answer on this much clearer.
Is Overloading compile time or runtime? Why do they call this for
overloading and overriding?
Compile time. In overriding the decision that method of which class is to be called is decided at runtime, hence it is runtime.
In overloading the method definition, availability based on the parameters passed in the method call is checked at compile time only.
Java does not identify methods by their names alone, but by their signatures. A signature is composed of the method name and the ordered list of parameter types. So, from a compiler and jvm point of view, those are two completely different methods. The fact that they share the name (and as a consequence a similar signature) has no meaning if not for humans.
Since signatures are used in .class files, the compiler is responsible for computing the signature of a method call, using method name and parameters, at compile time. The late binding that happens at runtime is related to polymorphism, beacuse the current instance on which a certain method is called could be an instance of a subclass that override a certain method, wether that method is also overloaded or not, in java, is not considered by the runtime at all.
You cannot have two method with the same signature in the same class. Notably, the return type of a method is not part of its signature, so you cannot have two method with the same and and same parameters but returning two different types.
In other languages, javascript for example, since parameters are always dynamic, the signature is only composed of the name of the method, which makes overloading impossible
As to the first part of your question, yes the code you showed is an example of overloading, well, assuming the first part is correct and the 0 in the second part is a typo.
I'm not familiar with how these topics are formally taught these days, but to my mind overloading isn't really related to polymorphism. It's just a convenient way for methods that more or less do the same thing (and often call each other) to share a name. I have no idea how to answer your second question. What is an "OOP branch"?
Again, I'm not quite sure how these tie in. Doesn't it depend on what the method actually does?
Well, think about it this way. In Java, when you call a method in general, leaving overloading aside, at what phase does the system figure out which method you're calling (as opposed to which class's implementation of that method)? As to the origin of those terms, honestly that should be pretty easy to look up.
Since function overloading can work very well without objects, I do not see any reason for it to be an OOP concept at all. For the question whether it's polymorphism, it does fulfill the general requirements and according to Wikipedia is a form of polymorphism.
In general, when you create a method you always do both (you abstract away some general functionality and you hide the information of the internal workings of the function). Overloading does not add to neither, IMO. (Even though through overloading and the gained polymorphism you could argue to gain in abstraction, since the function becomes more generic, it is IMO still on the same level of abstraction.)
Overload resolution is - which was suprising to me at first - compile time. This is in contrast to the mentioned overriding. (So its in that sense not the same kind of polymorphism, as one is runtime and the other one is compile time.)
Here's an example using multiple interface inheritance in Java and there's an issue.
Note that I fully know why there's an issue and this is not the point of my question. The question is about how you name this particular multiple interface inheritance ambiguity, if there's a name for it.
For example, in C++, the ambiguity that arises when you use multiple implementation inheritance and cannot determine which overridden method to use is called the "diamond problem":
http://en.wikipedia.org/wiki/Diamond_problem
Now once again, I know this is not the same problem here: that's not the point. The point is that a name has been coined in that previous case.
And I'd like to know if a name exists for the issue I'm about to describe.
Here's an example of another kind of multiple inheritance, where one interface inherits from two other interfaces that have an incompatible method return type:
interface A {
void a();
Integer c();
}
interface B {
void b();
Long c();
}
interface MI extends A, B {...}
(notice multiple interface inheritance at work using the 'extends' keyword)
You cannot do that, because:
types A and B are incompatible; both
define c() but with unrelated return
type
Has a name been coined to describe that situation?
I'm not sure there is a specific name for it, or at least it doesn't seem to be very commonly used. It's "just" a problem of the implicit mapping of interface methods to class methods; if you could have overloads which differ in return types only, there would be no problem either. So it comes down to an signature/overloading/implicit method mapping problem.
In the "Thinking in Java" online book, there isn't a name for it either.
http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ310_001.htm
Just a side-note, C# allows explicit interface implementations, which addresses this problem.
JLS §6.4.4, The Members of an Interface Type calls such duplicate superinterface members ambiguous, and requires a compile-time error. I was hoping for something colorful such as the Beaujolais Effect, Heisenbug, et al. Maybe two's-a-crowd?
I also don't know of any specific name for this problem. Whenever it arised it was described in a sentence containing the words return type incompatibility at some point. You could also call it the Map/Set incompatibilty as this is one of the more prominent and annoying examples in the Java class libraries. It makes it impossible to have the same class implement Map as well as Set or Collection just because Map defines a remove(Object) method with a different return type than Collection.
public interface Collection<E> extends Iterable<E> {
boolean remove(Object o);
}
public interface Set<E> extends Collection<E> {
}
public interface Map<K,V> {
V remove(Object key);
}
I'd hesitate to call this a multiple inheritance issue, because interfaces merely describe well, interface--a set of methods an implementing class must define--rather than any implementation. Extending an interface with other interfaces doesn't really mean the subinterface inherits from the superinterface, but rather that the subinterface is, in essence, a concatenation of the methods defined in the two.
If a third interface is used to extend the subinterface and provides a conflicting method declaration, it's essentially the same as if you had just provided the same two conflicting methods in the same interface.
I don't remember if I have ever seen any name for this. In Java Language Specification there is no name for this either.
The issue you describe exists in .NET as well as Java, but has a simple solution there: the .NET framework allows a class to implement an interface member using a class member with a different name. Thus, although the class methods which implement two interface members which differ only in return type are required to have different names, that does not preclude their ability to implement interface members with the same name.
If an interface inherits two interfaces with conflicting members, a class which implements the composite interface may implement the members just as if it had inherited the conflicting interfaces directly. Consumers of the combined interface will generally not be able to use the members of either component interface without a converting the reference to one of the other interface types, but the cast in question will be considered an upcast rather than an downcast.
The scheme implemented in .NET works nicely there. Unfortunately, there's no way to do anything similar in Java. I don't know that Java will squawk if an interface inherits other interfaces with conflicting members, but whether or not it squawks at that point, there would be no way to produce a class which could implement it.
I don't think a name has been defined because interfaces in Java cannot have method implementation, the problem is therefore avoided since there is always only one implementation to a specific method and hence no ambiguity will arise.
Have I missed the point or are you talking about the 'c' variable?