I was having an exam in Java today and the examiner asked me if I can provide any examples of using polymorphism in my Spring Boot project.
As I couldn`t think of anything at first, he pointed out that I have overriden toString() in my models and that this is dynamic/runtime polymorphism.
However, I am not sure that I understand his point, because to my understanding, a behavior is considered polymorphmic when we have a parent class reference variable pointing to a subclass object (focusing on dynamic polymorphism).
Then at runtime the actual object, to which the parent class variable points to, is fetched and its method is called, as explained nicely here.
However, I do not use upcasting in my project (i.e. initializing my POJO classes with an Object class variable).
Thus, my question is - is overriding toString() considered polymorphism, although the parent class (Object) is never used as a reference variable?
All exampes of runtime polymorphism that I find on Stackoverflow, including the ones here and this one with toString, illustrate a situation where we have a parent class variable pointing to a subclass object, e.g:
Object object = new User("petar");
String name = object.toString(); // assign to variable for clarity`s sake
System.out.println(name);
// prints petar
Where my User class is:
public class User {
String name;
public User(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
However, in my project I simply create users and other POJO classes with their own reference variables, e.g:
User user = new User("petar");
String name = user.toString();
System.out.println(name);
// prints petar, as toString is overriden
Is the above considered polymorphism, although there is no upcasting / parent reference variable involved?
My classmate argues that it is, because for non-final instance methods, the compiler doesn`t know which method to call - it only ensures that there is such method in the superclass, so it prolongs this decision up until runtime (late binding) by inserting an instruction into the compiled code, which is checked then and the actual object, to which the variable points to, is fetched, and its method is called (source).
However, in this article it is stated that:
Method Overriding is an example of runtime polymorphism. When a parent
class reference points to the child class object then the call to the
overridden method is determined at runtime, because during method call
which method(parent class or child class) is to be executed is
determined by the type of object. This process in which call to the
overridden method is resolved at runtime is known as dynamic method
dispatch.
So: is method overriding sufficient for polymorphism, or is it a requirement that there is a parent class reference to the subclass object? Am I safe to say at interviews that merely overriding toString() is an example of polymorphism?
Thanks to the comments and a few other sources, I believe I can now answer my question as follows:
One could argue that overriding toString() is an example of polymorphism because:
The Java Virtual Machine (JVM) always selects the method to invoke on non-final instance methods based on the object that it is referenced to, and not the method defined by the variable type. This is known as dynamic method invocation or late binding i.e - the decision which method to call happens at runtime, hence the wording "runtime" polymorphism. Source: Oracle Docs, JavaWorld.
Thus, regardless whether we consciously use polymorphism by e.g. programming to interfaces or we do a simple toString() method override, but still continue to use our classes with their own class variables (i.e. using a "User" variable instead of the parent class "Object" variable), a decision about which method to call is always made on runtime by checking the type of object our variables are referring to.
Thus, the evaluation on which model to call (i.e. the polimorphic behavior) happens, regardless which of the two initializations we use:
User user = new User("username1");
System.out.println(user);
// or
Object object = new User("username1");
System.out.println(object);
The type of the variable is insignificant for our question, what matters is the object that it is referring to, and which of all possible objects it refers to (i.e a parent or a child), is decided on runtime.
The type of the variable is only relevant to either limit the scope of available methods to the ones in the parent class and potentially overridden by its children (if we use a parent class reference variable) or to gain access to the specific methods of the child (if we use a child class reference variable).
For example, if we added a new method to our User class:
public String instanceMethod () {
return "User instance method called";
}
It would not be available through a Object class variable:
It would only be available through a User class variable.
Hope this clears the confusion for everyone else that needs a more detailed explanation too.
Related
i'm trying in this question to resolve this problem. When referencing a child class using a parent class reference, we call the parent class's methods.
class Programmer {
void print() {
System.out.println("Programmer - Mala Gupta");
}
}
class Author extends Programmer {
void print() {
System.out.println("Author - Mala Gupta");
}
}
class TestEJava {
Programmer a = new Programmer();
Programmer b = new Author();
b.print();
}
Following this code, I get the output like this 'Author - Mala Gupta'; despite that I should get the parent's method executed.
Can you explain to me what's happening behind the scenes.
You should not get 'Programmer - Mala Gupta' output, because you're creating the Author object:
new Author();
Programmer in this case is just a reference to the object. And this reference can point at any object of Programmer and its subclasses.
But, when you invoke a method, you invoke it on the object pointed by the reference. And that's Author.
Programmer is the parent class and Author is the child of Programmer. Parent class contain the reference of child class object but you can only call those methods which are in Parent class.
In Programmer b actually there is a reference of Author class. Thats why it called the Author class function. its called Polymorphism.
When an overridden method is called through a superclass reference, Java determines which version of that method to execute based upon the type of the object being referred to at the time the call occurs. Thus, this determination is made at run time.
It is the type of the object being referred to (not the type of the reference variable) that determines which version of an overridden method will be executed.
Therefore, if a superclass contains a method that is overridden by a subclass, then when different types of objects are referred to through a superclass reference variable, different versions of the method are executed. That's why you are getting output : Author - Mala Gupta
This concept is linked with Runtime Polymorphism. Here, the reference variable "b" belongs to the parent class (Programmer) and object belongs to the child class (Author).
Now, reference variable "b" is pointing to the child (Author) class.
There are two definition for print() method one belongs to the Programmer and another belongs to the Author class.The determination of the method to be called is based on the object being referred to by the reference variable. The process in which call to a function will resolve at run time.
So whenever you call b.print(), you'll be getting output as:
I'm wondering why Java has this strange behavior regarding a superclass and a subclass having instance variables with the same name.
Let's say we have the following class definitions:
class Parent {
int var = 1;
}
class Child extends Parent {
int var = 2;
}
By doing this, we are supposed to have hidden the superclass's variable var. And if we do not explicitly specify a way to access Parent's var via a super call, then we should never be able to access var from an instance of a child.
But when we have a cast, this hiding mechanism breaks:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.var); // prints out 1, instead of 2
Doesn't this completely circumvent the whole point of field hiding? If this is the case, then doesn't that render the the idea completely useless?
EDIT: I am referring specifically to this article in the Java Tutorials. It mentions
Within the subclass, the field in the superclass cannot be referenced
by its simple name. Instead, the field must be accessed through super...
From what I read there, it seems to imply that the developers of Java had some kind of technique in mind in doing this. Though I agree that it is a rather obscure concept and would probably bad practice in general.
In Java, data members are not polymorphic. This means that Parent.var and Child.var are two distinct variables that happen to have the same name. You're not in any sense "overriding" var in the derived class; as you have discovered yourself, both variables can be accessed independently of one another.
The best way forward really depends on what you're trying to achieve:
If Parent.var should not be visible to Child, make it private.
If Parent.var and Child.var are two logically distinct variables, give them different names to avoid confusion.
If Parent.var and Child.var are logically the same variable, then use one data member for them.
The "point" of field hiding is merely to specify the behaviour of code which does give a variable the same name as one in its superclass.
It's not meant to be used as a technique to genuinely hide information. That's done by making the variables private to start with... I would strongly recommend using private variables in virtually all cases. Fields are an implementation detail which should be hidden from all other code.
Attributes are not polymorphic in Java, and anyway declaring a public attribute is not always a good idea. For the behavior you're looking for, it's better to use private attributes and accessor methods, like this:
class Parent {
private int var = 1;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
class Child extends Parent {
private int var = 2;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
And now, when testing it, we get the desired result, 2:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.getVar());
This scenario is known as variable hiding, When the child and parent class both have a variable with the same name, child class's variable hides parent class's variable and this process is called variable hiding.
In Java variables are not polymorphic and Variable Hiding is not same as Method Overriding
While variable hiding looks like overriding a variable similar to method overriding but it is not, Overriding is applicable only to methods while hiding is applicable variables.
In the case of method overriding, overridden methods completely replaces the inherited methods so when we try to access the method from parent's reference by holding child's object, the method from child class gets called.
But in variable hiding child class hides the inherited variables instead of replacing, so when we try to access the variable from parent's reference by holding child's object, it will be accessed from the parent class.
public static void main(String[] args) throws Exception {
Parent parent = new Parent();
parent.printInstanceVariable(); // Output - "Parent`s Instance Variable"
System.out.println(parent.x); // Output - "Parent`s Instance Variable"
Child child = new Child();
child.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(child.x);// Output - "Child`s Instance Variable"
parent = child; // Or parent = new Child();
parent.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(parent.x);// Output - Parent`s Instance Variable
// Accessing child's variable from parent's reference by type casting
System.out.println(((Child) parent).x);// Output - "Child`s Instance Variable"
}
As we can see in above when an instance variable in a subclass has the same name as an instance variable in a superclass, then the instance variable is chosen from the reference type.
Declaring variables with the same name in both child and parent create confusion we should always avoid it so there will be no confusion. And this is why we should also always stick to General Guidelines to create POJOs and declare our variables with private access and also provide proper get/set methods to access them.
You can read more on my article What is Variable Shadowing and Hiding in Java.
When you are casting, you effectively tell the compiler "I know better" - it suspends the normal strong-typing inference rules and gives you the benefit of a doubt.
By saying Parent parent = (Parent)child; you are telling the compiler "treat this object as if it were an instance of Parent".
On another note, you are confusing "information hiding" principle of OO (good!) with a field-hiding side-effect (usually bad).
As you pointed out:
we are supposed to have hidden the superclass's variable var
The main point here is Variables do not override as methods do, so when you call directly Child.var you are calling a variable directly from the Child class and when you call Parent.var you're calling a variable from the Parent class, no matter if they do have the same name.
As a side note I would say this is really confusing and shouldn't be allowed as valid syntax.
I am Learning Java, while trying to understand inheritance. I couldn't figure out why the overridden method at the subclass walk() executed but not the other xyz() method.
class Person{
public void walk() { System.out.println("walking like a person "); }
}
public class Soldier extends Person{
#override
public void walk() { System.out.println("marching like a soldier "); }
public void xyz() { System.out.println("xyzng like a pro"); }
public static void main(String[] args) {
Person sp = new Soldier();
sp.walk();
sp.xyz();
}
}
Here is my question, if the following method call works fine and calls the Soldier method walk,
sp.walk();
why the compiler complain about the this call?
sp.xyz();
At the compile time parent class reference 'sp' can only see method inside it. if you want to access as ((Soldier) sp).xyz()
You may want to take a look at this answer.
Basically, xyz method is defined in a subclass of Person and in general case compiler can't know (and should not know) whether the referenced instance is Soldier or some other subclass which does not define xyz method.
In Java, "objects" are not values themselves -- they must always be manipulated through references; when you create an object, you get a reference; when you access a field or call a method, you do it through the reference. When you assign one reference to another, it copies the reference, so you have multiple pointers to the same object.
Your question asks why Soldier.xyz() is not accessible when the
Soldier object is stored in a Person reference. The answer is the
intersection of "polymorphism" and "static typing". Because Java is
statically typed at compile time you get certain guarantees from the
compiler but you are forced to follow rules in exchange or the code
won't compile. Here, the relevant guarantee is that every instance of
a subclass (e.g. Soldier) can be used as an instance of its super
class (e.g. Person).
Please take a look at this it is explained in more details thread
As of the tutorial guide to truly understand the inheritance please take a look at this article
That's clear.
because your reference to object(sp) is of type Person, that means sp contains all property and methods of Person only.
Even you get instance of Soldier, but your reference is from Person type yet.
Person is a class.
sp is an object, it is an instance of Person
Class Person haven't method named xyz(), thereforce sp.xyz() not working.
(You have a typo, we use #Override, not #override)
In the compile-time, IDE only knows about the static Object type is Person class. You can see compile-time reference rule here: https://www.cs.cornell.edu/courses/JavaAndDS/files/compiletimeReferenceRule.pdf
We always say that method overloading is static polymorphism and overriding is runtime polymorphism. What exactly do we mean by static here? Is the call to a method resolved on compiling the code? So whats the difference between normal method call and calling a final method? Which one is linked at compile time?
Method overloading means making multiple versions of a function based on the inputs. For example:
public Double doSomething(Double x) { ... }
public Object doSomething(Object y) { ... }
The choice of which method to call is made at compile time. For example:
Double obj1 = new Double();
doSomething(obj1); // calls the Double version
Object obj2 = new Object();
doSomething(obj2); // calls the Object version
Object obj3 = new Double();
doSomething(obj3); // calls the Object version because the compilers see the
// type as Object
// This makes more sense when you consider something like
public void myMethod(Object o) {
doSomething(o);
}
myMethod(new Double(5));
// inside the call to myMethod, it sees only that it has an Object
// it can't tell that it's a Double at compile time
Method Overriding means defining a new version of the method by a subclass of the original
class Parent {
public void myMethod() { ... }
}
class Child extends Parent {
#Override
public void myMethod() { ... }
}
Parent p = new Parent();
p.myMethod(); // calls Parent's myMethod
Child c = new Child();
c.myMethod(); // calls Child's myMethod
Parent pc = new Child();
pc.myMethod(); // call's Child's myMethod because the type is checked at runtime
// rather than compile time
I hope that helps
Your are right - calls to overloaded methods are realized at compile time. That's why it is static.
Calls to overridden methods are realized at run-time, based on the type on which the method is invoked.
On virtual methods wikipedia says:
In Java, all non-static methods are by default "virtual functions." Only methods marked with the keyword final are non-virtual.
final methods cannot be overridden, so they are realized statically.
Imagine the method:
public String analyze(Interface i) {
i.analyze();
return i.getAnalysisDetails();
}
The compiler can't overload this method for all implementations of Interface that can possibly be passed to it.
I don't think you can call overloading any sort of polymorphism. Overloaded methods are linked at compile time, which kind of precludes calling it polymorphism.
Polymorphism refers to the dynamic binding of a method to its call when you use a base class reference for a derived class object. Overriding methods is how you implement this polymorphic behaviour.
i agree with rachel, because in K&B book it is directly mentioned that overloading does not belong to polymorphism in chapter 2(object orientation). But in lots of places i found that overloading means static polymorphism because it is compile time and overriding means dynamic polymorphism because it s run time.
But one interesting thing is in a C++ book (Object-Oriented Programming in C++ - Robert Lafore) it is also directly mentioned that overloading means static polymorphism.
But one more thing is there java and c++ both are two different programing languages and they have different object manipulation techniques so may be polymorphism differs in c++ and java ?
Method Overloading simply means providing two separate methods in a class with the same name but different arguments while method return type may or may not be different which allows us to reuse the same method name.
But both methods are different hence can be resolved by compiler at compile time that's is why it is also known as Compile Time Polymorphism or Static Polymorphism
Method Overriding means defining a method in the child class which is already defined in the parent class with same method signature i.e same name, arguments and return type.
Mammal mammal = new Cat();
System.out.println(mammal.speak());
At the line mammal.speak() compiler says the speak() method of reference type Mammal is getting called, so for compiler this call is Mammal.speak().
But at the execution time JVM knows clearly that mammal reference is holding the reference of object of Cat, so for JVM this call is Cat.speak().
Because method call is getting resolved at runtime by JVM that's why it is also known as Runtime Polymorphism and Dynamic Method Dispatch.
Difference Between Method Overloading and Method Overriding
For more details, you can read Everything About Method Overloading Vs Method Overriding.
Simple Definition - Method overloading deals with the notion of having two or more methods(functions) in the same class with the same name but different arguments.
While Method overriding means having two methods with the same arguments, but different implementation. One of them would exist in the Parent class (Base Class) while another will be in the derived class(Child Class).#Override annotation is required for this.
Check this :
Click here for a detailed example
Property Over-loading Overriding
Method Names -------------->must be Same----------------must be same
Arg Types------------------>must be Different(at least arg)
Method Signature
Return Type
Private,Static,Final
Access Modifier
try/Catch
Method Resolution
First, I want to discuss Run-time/Dynamic polymorphism and Compile-time/static polymorphism.
Compile-time/static polymorphism:- as its name suggests that it bind the function call to its appropriate Function at compile time. That means the compiler exactly know which function call associated to which function. Function overloading is an example of compile time polymorphism.
Run-time/Dynamic polymorphism:-In this type of polymorphism compiler don't know which functions call associates to which function until the run of the program. Eg. function overriding.
NOW, what are the function overriding and function overloading???
Function Overloading:- same function name but different function signature/parameter.
eg. Area(no. of parameter)
{ -------------
----------------
return area;}
area of square requires only one parameter
area of rectangle requires two parameters(Length and breadth)
function overriding:- alter the work of a function which is present in both the Superclass and Child class.
eg. name() in superclass prints "hello Rahul" but after overring in child class it prints "hello Akshit"
Tried to cover all differences
Overloading Overriding
Method Name Must be same Must be same
Argument Types Must be same Must be different
Return Type No restriction Must be same till 1.4V
but after 1.4V
co- variants
were introduced
private/static/final Can be overloaded Cannot be overridden
Access Modifiers No restriction Cannot reduce the scope
Throws keyword No restriction If child class method
throws a checked
exception the parent
class method must throw
the same or the
parent exception
Method Resolution Taken care by compiler Taken care by JVM based
based on reference types on run-time object
Known as Compile-Time Polymorphism, RunTime Polymorphism,
Static Polymorphism, or dynamic polymorphism,
early binding late binding.
This is a purely theoretical question.
Given three simple classes:
class Base {
}
class Sub extends Base {
}
class SubSub extends Sub {
}
And a function meant to operate on these classes:
public static void doSomething(Base b) {
System.out.println("BASE CALLED");
}
public static void doSomething(Sub b) {
System.out.println("SUB CALLED");
}
It seems that the followign code:
SubSub ss = new SubSub();
doSomething(ss);
could legitimately result in printing either BASE CALLED, or SUB CALLED, since SubSub can be casted to both of those. In fact, removing the Sub version of the function causes BASE CALLED to be printed. What actually happens is that "SUB CALLED" is printed. This seems to mean that which function is called doesn't depend on the order the functions are defined in, as the Base version was called first.
Does Java just look at all the different versions of the function and pick the one which requires the smallest traversal up the inheritance stack? Is this standardized? Is it written out in any documentation?
The formal specification can be found in part 15.12.2.5 of the Java Language Specification (JLS). Thanks to generics this is pretty complicated, so you might want to look at same section of the first edition of the JLS.
It basically says that the compiler tries to find a version of the method where all parameters including the object the method is called upon are most specific. If no such method exists (e.g. since you have method(Base, Sub) and method(Sub, Base) but not method(Sub, Sub)), then the compilation fails.
Note that the actual choice of method depends on the dynamic type of the target object for instance methods, but not for the parameters. Your example would still work the same on the instance level.
You should be able to give the compiler a helping hand by casting or redeclaring the type of ss. If the declared type of the variable matches a signature exactly then everything is clear for the compiler and maintenance programmers as well. It doesn't matter if you then assign a more specific type as long as the declared type matches.
As far as I know, Java and C++ make this decision at compilation time (since these are static functions that are not dynamically dispatchable) based on the most specific matching that they can make. If your static type is SubSub and you have an overload that takes SubSub, this is the one that will be invoked. I'm fairly sure it's in both standards.
If you have a reference or pointer to Base, even if it contains a Sub or a SubSub, you will match the version that takes a Base because at compile time, that is the only assurance that the compiler has.
When you have overloaded static methods then it calls that method that is defined immediately in the class which is invoking the method. If however, no method is defined in the calling class then it will invoke the method inherited from its immediate parent class.
In your case there are two overloaded methods both of which can accept SubSub as parameter. the compiler checks for the most specific match and goes for it. But the most specific match is generally the lowest in the type hierarchy.
EDITED
Removed the conflicting statement. Two methods in classes that are at the same type hierarchy level can't be in ambiguous state for the compiler to choose. This ambiguity is possible only in the case of multiple inheritance.
Java binds methods dynamically (in runtime, depending on object instance type, not reference type) but only in context of one method signature. Java binds method signature statically (at compilation time).
In other words, Java makes decision what method (signature) should be called in compile time (statically - reference based - overloading). In runtime Java will take that signature, find proper object in object type hierarchy and execute that method on that dynamically binded object.
Overloading -> what (method signature at compilation time)
Overriding -> from where (object in type hierarchy at runtime)