Whats the real time example of dynamic polymorphism in java - java

What is the real time example of dynamic polymorphism in java?
I have been asked so many places this question in interview
but dint got real answer. Code:
class A {
public void m1() {}
}
class B extends A {
public void m1() {}
}
class manage {
A a1 = new A();
B b1 = new B();
A a2 = new B();
//when i will call A's m1 it will call m1 of A
a1.m1();
//when i will call B's m1 it will call m1 of B
b1.m1();
//when i will call B's m1
a2.m1();
}
in the above code by looking , i can say its whose object will be called then why its run time polymorphism
Anyone can please help the real time correct example of runtime/dynamic polymorphism ??

Lets change your code example just a little bit. Instead of having a test class that defines the objects to test, we only offer a method taking some arguments:
public void testCalls(A a1, A b1, A b2) {
a1.m1();
...
Now, can you still say what will happen? "Hmm, that will depend on what gets passed to the method call?!"
In your example, you know what is going to happen because you can easily deduct the true nature of all objects. But what if you don't have that information? When you are only providing an interface, and the incoming objects aren't showing up in your source code?!
Thus: what matters is the true type of an object at runtime. Of course, when you construct a simple example, you always know that true type. But the things that matter in the real world are simply not that simple.

"Dynamic polymorphism is the polymorphism existed at run-time".
That mean Java compiler does not understand which method is called at compilation time. Only JVM decides which method is called at run-time.
In your example, the compiler don't know the behavior of a2.m1(). However, at the runtime, the JVM will invoke the code which was defined in the class B.
class A {
public void m1(){
System.out.println("Inside A's m1 method");
}
}
class B extends A {
// overriding m1()
public void m1(){
System.out.println("Inside B's m1 method");
}
}
class C extends A {
public void m1(){
System.out.println("Inside C's m1 method");
}
}
// Driver class
class Dispatch {
public static void main(String args[]) {
// object of type A
A a = new A();
a.m1(); // calling m1 of A
a = new B();
a.m1(); // calling m1 of B
a = new C();
a.m1(); // calling m1 of C
}
}
Results:
Inside A's m1 method
Inside B's m1 method
Inside C's m1 method

As the name suggests, it happens in realtime aka runtime.

Related

what's the use of java virtual method invokation?

Say I have the following code
public class A {
public void callme() {
System.out.println("Calling of class A function ");
}
}
public class B extends A {
public void callme() {
System.out.println(" Calling of class B fuction ");
}
public void Hello() {
System.out.println("hello guys");
}
}
and a main() that does the following
public class Main {
public static void main(String [] args){
A a = new B();
B b = new B();
b = (B)a;
a.callme();
b.callme();
a.Hello(); // show error : Hello is undefined for method A
}
}
The book says "you get the behavior associated with the object to which the variable refers at runtime". Ok, I get behavior of B class when a method callme is called, but when I access the method Hello, it shows an error that Hello is undefined for method A. why is that?
Polymorphism doesn't work this way. Since A is parent of B, B can inherit methods of A (like son can inherit properties of father), but its not vice versa because A doesn't know which classes are inheriting it (A does not know who are its children.)
For Example, suppose there is one more class C:
public class C extends A {
public void callme(){
System.out.println(" Calling of class C fuction ");
}
public void Hello(){
System.out.println("hello guys, I am C");
}
}
Now, if you use
a.Hello();
how will a know which child class it should call since it does not methods of its child. only its own abstract method, which it knows child will implement for sure.
a is of type A, even if it is referring to an instance of B.
A doesn't have the Hello method (even an abstract declaration). So your compiler emits the error. Adjusting your code slightly to
public abstract class A {
public abstract void Hello();
/*the rest as before*/
would be a fix. A is then assuming the characteristics of an interface.
public class B extends A {
public void callme(){
System.out.println(" Calling of class B fuction ");
}
public void Hello(){ // hello method is only the part of class B not A.
System.out.println("hello guys");
}
}
In above class hello() method is a part of B only. it not override by the method of A.
now in your main method call
public static void main(String [] args){
A a= new B(); // object of b referred by (a) Reference Variable of A
B b= new B(); // object of b referred by (b) Reference Variable of B
b= (B)a;
a.callme(); //override takes place and method of B's Callme() called
b.callme(); //again override takes place here and method of B's Callme() called
a.Hello();// buttttttt
b.Hello(); // this will compile and executes fine.
}
}
Here you used the reference variable of class A which don't have any method name Hello(). So, Method Resolution will not take place(won't be able to find any method like Hello()).
but if you try to call b.Hello() using the reference variable of B then it will work fine to you.
Now suppose there is another class C which is a sub class of A and contains a Method Name Hello().
public class C extends A {
public void Hello(){ // hello method is only the part of class B not A.
System.out.println("hello guys");
}
}
In main a Statement like this
A a = new C();
and if you try to call a.Hello() then which Hello() method will call. Compiler will get confused.
So, This concept work only when you try to override the method of super class in sub Class.
Is the parent class aware of classes derived from it ?
Casting does not change the actual object type. Only the reference type gets changed.
I highly recommend you my upcasting and downcasting writing from the link

forcing invocation of base class method

How does one force to invoke A's foo() method when working with instance of B (from main, and not through super call) ?
I could swear I've seen it done before. Perhaps it was C++ ??
public class Test {
static class A {
public void foo() {
System.out.println("A");
}
}
static class B extends A{
public void foo() {
System.out.println("B");
}
}
public static void main(String[] args) {
A a = new A();
B b = new B();
A aa = new B();
a.foo();
b.foo();
((A)aa).foo(); // want to print A here!
}
}
I could swear I've seen it done before. Perhaps it was C++?
The keyword here is virtual. This is possible in languages like C++ and C# because it's up to the programmer to define the method as virtual. I've adapted this code to C++:
#include <iostream>
using namespace std;
class A {
public:
void foo() {
std::cout << "A" << endl;
}
};
class B: public A {
public:
void foo() {
std::cout << "B" << endl;
}
};
int main() {
// your code goes here
A* a = new A();
B* b = new B();
A* aa = new B();
a->foo();
b->foo();
aa->foo();
return 0;
}
Prints:
A
B
A
Now, using the virtual keyword (just posting the relevant code from above example):
class A {
public:
virtual void foo() {
std::cout << "A" << endl;
}
};
Prints:
A
B
B
In Java you cannot expect this because all methods are virtual by default. So, to your question:
How does one force to invoke A#foo when working with instance of B and not through super call?
In Java, you can't.
You can't call the super method in other objects - that would violate encapsulation. The whole point is that the object controls what its overridden methods do. For instance, you might override a collection's add method to throw an exception in certain circumstances, so it could ensure only "valid" items got added to the collection. That would be pointless if callers could just bypass it with a cast!
The only reason an object gets to call super.foo() for itself is to enable one call to be implemented by using the parent implementation. It's up to the code in the class to make sure it only ever does that sensibly. Again, to take the add-in-a-collection example, if the collection overrides add it would have to have some way of adding the validated item to the collection, which it would do with super.add().
From outside the class definitions of A and B, you cannot force the superclass method to run. B has overridden it, so if an A reference refers to a B, B's foo method will run and print "B". No changes outside of these classes can change this polymorphic behavior -- having an actual B object will print "B".
To force it to print "B", you must change code in the A/B classes. You can mark foo as final in A so that B can't override it. Optionally, you can optionally include another method call in A's foo that B can override, so that A can guarantee that "A" will be printed, but B can still do whatever it wants when foo is called.
static class A {
public final void foo() {
System.out.println("A");
// Optional.
bar();
}
protected void bar() {}
}
static class B extends A {
// Can't override "foo" now -- can't prevent "A" from being printed.
//public void foo() {
// System.out.println("B");
//}
// Optional.
#Override
protected void bar() {
System.out.println("B");
}
}
Here, foo will always print "A", but B can also print "B" if it really wants.

Java Vs C#: Java and C# subclasses with method overrides output different results in same scenario

Ok! I have same code written in Java and C# but the output is different!
class A
{
public void print()
{
Console.WriteLine("Class A");
}
}
class B : A
{
public void print()
{
Console.WriteLine("Class B");
}
}
class Program
{
static void Main(string[] args)
{
A a = new B();
a.print();
Console.Read();
}
}
Output: Class A. It is in C#.
But when same code was ran in Java, the output was Class B. Here is the Java Code:
class A
{
public void print()
{
System.out.println("Class A");
}
}
class B extends A
{
public void print()
{
System.out.println("Class B");
}
}
public class Program{
public static void main(String []args){
A a = new B();
a.print();
}
}
So, why this is showing different results? I do know that, in Java, all methods are virtual by default that's why Java outputs Class B.
Another thing is that, both languages claim that they are emerged or inspired by C++ then why they are showing different results while both have same base language(Say).
And what does this line A a = new B(); actually doing? Isn't a holding object of class B? If it is so, then why C# displays Class A and Java shows Class B?
NOTE This question was asked in interview with the same code provided above. And I answered with output Class B (with respect to Java) but he said Class A will be right output.
Thank you!
This is because in C# methods of derived classes hide, not override, methods of their base class. The methods that you would like to override need to be explicitly marked with the keyword virtual in the base, and with the keyword override in the derived classes.
In contrast, in Java all methods are virtual by default: simply specifying the same signature is sufficient for an override.
Here is how to make your C# program an equivalent of Java program:
class A
{
public virtual void print() // Add "virtual"
{
Console.WriteLine("Class A");
}
}
class B : A
{
public override void print()// Add "override"
{
Console.WriteLine("Class B");
}
}
After A a = new B(), variable a is holding object of B but the output is "Class A"! Shouldn't it call method of class B?
When you hide a method, rather than overriding it, your derived class keeps both methods - the one in the base class, and the one in the derived class. Both these methods remain accessible to the outside callers. They can decide which of the two methods to call by using an object of an appropriate static type. Here is an example:
B b = new B();
b.print(); // Prints "Class B"
((A)b).print(); // Prints "Class A"
Demo on ideone.
When you use virtual/override, you can access only one method from the outside - namely, the one in the derived class. The method in the base class can be accessed by methods of the derived class, but not by the outside users of the derived class.
In Java, non-static methods are virtual, whereas in C#, they are not. You will need to use the virtual and override keywords on your print method to get the same behaviour in c#.
Polymorphic behaviour in C#:
class A
{
public virtual void print()
{
Console.WriteLine("Class A");
}
}
class B : A
{
public override void print()
{
Console.WriteLine("Class B");
}
}
Edit
Getting back to your original C# code, you will get a compile time warning on B.print when you use the same method signature in both a subclass and its superclass, viz:
The keyword 'new' is required on 'print' because it hides method
'MyNamespace.A.print()'
This is a good indication that the method won't be called polymorphically / virtually. To avoid the warning (and retain your original C# behaviour), in B you would need to add new:
public new void print()

How Does the JVM handle Dynamic Dispatch in this Situation?

Given the following source and ouput:
Source:
public class A
{
public void foo()
{
bar();
}
public void bar()
{
System.out.println ("in A's bar() method");
}
}
public class B extends A
{
#Override
public void foo()
{
super.foo();
// Do some specialized B stuff
}
#Override
public void bar()
{
System.out.println ("in B's bar() method");
}
}
public class Main
{
public static void main (String... args)
{
B b = new B();
b.foo();
}
}
Output:
in B's bar() method
Can someone please explain to me how the JVM is smart enough to polymorphically call B's (as opposed to A's) bar() method in this situation? I'd like to know what kind of dynamic dispatch magic is going on behind the scenes here.
Update: In case I wasn't clear enough, I know basically WHAT is happening, I'm looking for specific details on HOW the JVM makes it happen under the hood. The answers so far are too simplistic.
Update 2: Maybe I wasn't clear enough. When b.foo() is called, then super.foo() is called, then bar() is called in class A's foo(). How does the bar() that is called when specifically invoking super.foo() not call class A's bar() method, since the super keyword explicitly specifies class A? What steps does the JVM have to go through to sort this out?
Also, does this mean it's a bad idea in general to call public methods from within their own class since they can be overridden in this way?
Java uses the object's type when invoking the methods.
A b = new B();
b.foo();
Let's say you used above code.
Here what will happen is you are creating an object of type B and assign it to a reference of type A. Since the object type is B, you'll invoke the method in class B.
Even if the constructor or method you're currently in is defined in a super-class, the object doesn't change type. It will still be an object of type B. This can be demonstrated by using the this keyword.
this refers to the current object. That is not the same as the class defining the current method or constructor.
Try typing the following into A's constructor or in the foo() method:
System.out.println(this.getClass());
The function call sequence is (from eclipse debug view):
1. B.foo() // super.foo()
2. B(A).foo() // bar()
3. B.bar()
After the thread calls super.foo(), the JVM will check if there's any implementation in B (since we still hold B.class in the stack), if there is, JVM will call it.
This feature is guaranteed by JVM implementation. It is not smart, it just be designed this way, just like C++'s virtual methods.
Hope it helps.

Call method from instance

Let's say I have two classes, A and B, in turn have some methods, something() and nothing() and an instance of B is created in A, as
public class A {
public A() {
B b = new B();
b.nothing();
}
public void something() {
...
}
}
A calling b.nothing() is all standard stuff, but is there any means which by instance b can call a.something(), assuming the instance of A is called a. If not, why is this conceptually wrong?
I don't think there's anything conceptually wrong with this.
However, for the mechanics to work, b needs to know which instance of A to call something() on. For this, either B's constructor, or its nothing() method, needs to take an A reference as an argument.
example 1:
public class B {
public void nothing(A a) {
...
a.something();
...
}
}
example 2:
public class B {
private final A a;
public B(A a) {
this.a = a;
}
public void nothing() {
...
this.a.something();
...
}
}
example 3:
There is a third way, applicable in some circumstances. If B is an inner class of A, it has an implicit reference to its associated instance of A.
public class A {
public void something() { ... }
public class B {
public void nothing() {
...
something();
...
}
}
}
is there any means which by instance b can call a.something()
You can't get hold of the caller in a method so, no, there's no way to do that.
If not, why is this conceptually wrong?
Two issues come to my mind immediately:
What would the type of the caller be? Since anyone could call b.nothing(), you can't assume more than that it's an Object which would result in lots of ugly down casts.
The implementation of b.nothing() shouldn't care about who's calling him. What happens if you refactor A and move the call to b.nothing() to some other class? It would be quite surprising if b.nothing() all of a sudden stopped working.
The only way b.nothing() can call a.something() is if you tell the instance of B about the instance of A. For example:
b.nothing(this);
where B.nothing looks like:
public void nothing(A a)
{
// Do other stuff
a.something();
}
Alternatively, you could pass in this in the constructor to B, which would keep hold of the reference:
B b = new B(this);
b.nothing();
Note that letting this escape during a constructor call is generally a bad idea - you're letting B.nothing() call A.something() on an object which isn't fully initialized yet - its constructor hasn't finished executing. That can lead to undesirable and hard-to-diagnose behaviour sometimes.
To do this, b would require a reference to a. There are two ways to provide that:
Pass such a reference in the constructor of B or give B an appropriate setter.
If B is an inner class of A, then it has such a reference implicitly.

Categories

Resources