I am new to JAVA and while studying I came across Dynamic Method Dispatch and this example confused me
class A {
void callme() {
System.out.println("Inside A's callme method");
}
}
class B extends A {
// override callme()
void callme() {
System.out.println("Inside B's callme method");
}
}
class C extends A {
// override callme()
void callme() {
System.out.println("Inside C's callme method");
}
}
class Dispatch {
public static void main(String args[]) {
A a = new A(); // object of type A
B b = new B(); // object of type B
C c = new C(); // object of type C
A r; // obtain a reference of type A
r = a; // r refers to an A object
r.callme(); // calls A's version of callme
r = b; // r refers to a B object
r.callme(); // calls B's version of callme
r = c; // r refers to a C object
r.callme(); // calls C's version of callme
}
}
if I just do this
a.callme();
b.callme();
c.callme();
I get the same result.
When i read about DMD by googling I didnt get satisfactory explanations. I just understood that it is late binding but not early binding and thats it. So it is just used to escape during compiling or is there something else. Is there any easy example to understand the benefit.
This is more commonly referred to as dynamic binding. It provides polymorphic behavior (Polymorphism is an OOP concept).
In Java, dynamic binding is done based on the actual type of the object. This means that regardless of the declared type of the object, the invoked method body will be the one declared in the class that was used to construct it (the runtime class). This is the class with which new was used.
When you assign r = a, and call r.callme(), Java (at runtime) will see that the class of the object that the variable r points to is A, and will therefore run the implementation of callme() provided by the class A.
Likewise, when you reassign r = b and call r.callme(), Java will see that the class of the object is B and will run B.callme.
Regarding the "why" part, the Java tutorial has states:
The dictionary definition of polymorphism refers to a principle in biology in which an organism or species can have many different forms or stages. This principle can also be applied to object-oriented programming and languages like the Java language. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class.
Related
class A {
public int a = 100;
}
class B extends A {
public int a = 80;
}
class C extends B {
public int a = 10;
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
}
}
What does ((A) this).a in the line System.out.println(((A) this).a); do?
Is it upcasting/downcasting thisor is something else happening here?
I also tried System.out.println(this); and System.out.println((A)this); and they both have the same output. What exactly is happening here?
In the java programming language, we have classes. When we write java code, we create instances of those classes, for example:
Object o = new Object();
Object is a class. Writing new Object() creates an instance of that class. The above code declares a variable o and assigns it [a reference to] an instance of class Object.
In the terminology of the java programming language, we say that variable o has type Object.
In the code in your question, a variable that is assigned an instance of class C, really has three types.
It has type C.
It has type B since B is the superclass of C.
It has type A because it indirectly extends class A also.
In the context of the code in your question, this is a special variable whose type is C. Writing (A) this is telling java to relate to the variable this as if its type is A.
Class A cannot access its subclasses. Hence it is only aware of its class member a. Hence when you write this line of code...
((A) this).a
You are accessing the member of class A only.
System.out.println(a);a is the one from the show method of your C class → a = 0
System.out.println(super.a);a is the one from the super-class of C, which is B → a = 80
System.out.println(((A) this).a);First, you cast your C instance (this) into A, then you call a which is a member of the A class → a = 100
There is also something to consider : method will always take the more specialized one (except if super is used), where field will be taken directly from the type referenced (even if there is an extending class).
For example, if I add getA() in each classes :
class A {
public int a = 100;
public int getA(){
return a;
}
}
class B extends A {
public int a = 80;
public int getA(){
return a;
}
}
class C extends B {
public int a = 10;
public int getA(){
return a;
}
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
System.out.println(getA());
System.out.println(super.getA());
System.out.println(((A) this).getA());
}
}
class Scratch {
public static void main(String[] args) {
new C().show();
}
}
I get the following output :
0
80
100
10
80
10
Which means that in the case of the method, except in the case of super.getA() which explicitly goes to the superclass, casting your C into a A doesn't change much for methods, as it impacts the field.
If you write something like obj.a, obj.getA() or someMethod(obj), Java somehow has to find the actual field or method to be used, based on the type or class of obj. There are two distinct dispatch mechanisms involved (plus the special construct super).
Dynamic dispatch (polymorphism, overriding): This is used when calling an instance method on the object, as in obj.getA(). Then the runtime class of the obj is examined, and if this class contains a getA() method, this is used. Otherwise, the direct parent class is examined for a getA() method, and so on up to the Object class.
Static dispatch: In cases like obj.a or someMethod(obj), the runtime class of obj doesn't matter. Involved is only the compiler, and from his knowledge of obj's type, he decides which field or method to use.
super dispatch: If you write super.getA() or super.a, your getA() method or a field is ignored, and instead the next-higher class in the hierarchy is used that contains such a method or field.
In your case you have 3 fields plus one local variable, all with the same name a. (By the way, it's a very bad idea to have such name conflicts in professional code.) We are inside a method show() declared in the C class. Let's have a look at some different expressions and what they mean here:
a references the local variable a. There's no dispatch needed, it's just that local definitions take precedence over fields.
this.a is a static-dispatch expression, so it's important what the compiler thinks about the type of this. And that's always the class where this code has been written. In your case, it's class C, so the field a from class C is used, the one being 10.
super.a is a super-dispatch expression, meaning that the a field from this class C is ignored and the next higher one taken (the one from B, in our case).
((A) this).a is static dispatch, but the (A) casting has a significant effect. The expression before the dot originally comes from this, being of type C, but the (A) cast tells the compiler to believe it were of type A. This is okay, as every C also is an A, by inheritance. But now, static dispatch sees something of type A in front of the dot, and dispatches to the a field from the A class, and no longer from C.
getA(), this.getA() and ((A) this).getA() are all dynamic-dispatch examples, all giving the same result. The method called will be the one based on the runtime class of this object. This will typically be one defined in the C class. But if show() was called on an object of a subclass of C, e.g. D, and D had its own getA() method, that one would be used.
super.getA() is a case of super-dispatch, it will call the getA() method next higher up in the class hierarchy from the current class, e.g. B.
System.out.println(this);
And
System.out.println((A)this)
These two prints the object reference to class C with toString() method.
System.out.println(((A)this).a);
This is upcasting, child object to parent object.
Let's say I have the following interface and classes defined:
public interface I { void a(); }
public class A implements I {
public void a() { System.out.println("A"); }
}
public class B implements I {
public void a() { System.out.println("B"); }
public void b() { System.out.println("C"); }
}
And then I run the following code:
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
I i;
i = a;
i.a(); // prints "A"
i = b;
i.a(); // prints "B"
i.b(); // 1st problem: i can't seem to find method b. Why?
b = i; // 2nd problem: b can't be assigned to i although i references an object of class B?
b = (B)i; // why does this work fine...
a = (A)i; // 3rd problem: ...but this here doesn't?
}
}
So here are my questions:
First Problem
Why can't i.b() be called?
i points to the same object as b, an object of class B which does have a method b.
So why does i.a() call the right method (the one that prints out "B") but i.b() doesn't resolve at all?
Does the fact that i was declared as being of type I (an interface) have anything to do with that? Does this mean that in an assignment X x = new Y() where Y extends X, one can only ever call methods on x that are already declared in X, and not just specific to Y?
Second Problem
Why can't b be assigned to i although i references an object of class B? b and i already reference the same object, don't they? So why does it cause an error if I try to assign b to i - the end result of which should be identical to the state of the program before that assignment, unless I'm missing something significant.
Third Problem
Why can I cast i to type B now although I couldn't assign b to i earlier, and why doesn't casting i to A work?
I'm assuming my confusion is somehow rooted in an unclear distinction between the reference variables and the objects they're referencing, as well as the differences between the types of these variables and objects. I just can't quite explain these occurrences - and in particular the first problem confuses me a lot.
For the first problem:
You can use the interface reference to call only the methods it declares
For the second problem:
You can use interface reference to invoke methods in the classes that implement the interface. However, there is no use to assign interface reference to a class reference since interface reference doesn't have any methods that can be invoked.
for the third problem:
You have assigned previously
i=b
and hence
b=(B)i
works fine.
However,
a=(A)i
wouldn't work because i stores b and not a
First of all, learn Java (and/or OO (object oriented)) programming...
Variable i is a reference to an object instance that implements interface I. Method b() was not declared in interface I, thus it is not visible through i.b().
To be able to call it, i needs to be casted, EG: ((B) i).b()
Variable b is a reference to an object that is an instance of class B, and cannot be assigned to any reference that itself is not declared as an instance of B.
Again, a cast needed, EG: b = (B) i
Class B is not a child of class A. They both implement interface I, but A is not parent of B.
It's not a problem at all but It's behavior of inheritance and polymorphism.
Please note that when you
I i = new A();
Left hand side (I) will tells compiler which all methods it can call using that reference.
Right hand side (A) will tells the runtime which method should execute using that method call
So in your case
1 Problem
you can not call b() since b() is not there in inteface I
2 Problem
you are casting interface to object b and then calling b() so its working fine.
This question already has answers here:
Downcasting in Java
(12 answers)
Closed 8 years ago.
I am getting an exception for the following code.
class A {
void foo() {
System.out.println("Running foo()");
}
}
class B extends A {
void foo() {
System.out.println("Overidden foo()");
}
}
public class Casting {
public static void main(String[] args) {
A obj = new B();
obj.foo();
// B ref = (B) obj;
// ref.foo();
B ref = (B) new A();
ref.foo();
}
}
But if I run
B ref = (B) obj;
ref.foo();
instead of
B ref = (B) new A();
ref.foo();
it works properly.
Can anyone explain what is happening here.?
obj is an instance of B because you created it using the contructor of class B. This is why B ref = (B) obj; works fine.
In B ref = (B) new A(); you are simply casting an object of type A created using the constructor of A (which is the parent class) to a subclass type which will cause a java.lang.ClassCastException. The opposite casting would work, i.e.
A ref = (A) new B();
ref.disp();
in which case you converting an instance of a subclass to its parent which is fine since an object of type B is also an instance of A.
It's pretty easy to explain.
By doing new A() you receive an A-object. Then you tell the JVM it's of type B, but that's obviously wrong and the JVM can't cast from A-type to B-type, how should Java know how to do that? It's not sure that A has the same methods as B. It's just a parent, B could have methods A hasn't. If you could cast from A to B you could have B objects that don't behave like B objects and don't have the B classes methods.
If you have a B-object you can treat it like a A-object because every B-object has at least the same methods, constructors and ivars.
An example using ducks:
Imagine you have got an abstract Duck class (but you didn't declared it as abstract). This class is the parent class of all other duck classes and also including RubberDuck. As reason of that the Duck class just has some basic methods like getSize but no method like walk or eat (a rubber duck can't eat herself).
What would happen if you create a duck object and downcast it to BuffleheadDuck and you would try to invoke the walk method? A BuffleheadDuck duck knows how to walk, but an abstract duck can't walk.
Let's say we have class A as a parent class, and class C that extends it.
class A
{
void m()
{
System.out.println("A.m");
}
}
class C extends A
{
#Override
void m()
{
System.out.println("C.m");
}
}
What's the difference between reference A a and C c when we use them to point to the same object type, for example A a = new C(); and C c = new C();?
From this question: Java inheritance vs. C# inheritance, it looks like that as a and c points to object type of C, and there seems no difference in using them.
I tested this code, and they all prints C.m.
class inherit {
void x(A a)
{
a.m();
}
public static void main(String[] args) {
System.out.println("hello");
A a = new C();
C c = new C();
a.m();
c.m();
new inherit().x(a);
new inherit().x(c);
}
}
That depends what the object is going to be used for.
If what you actually need is an object that has A's interface(i.e. A's type), it's strongly recommended to use A a = new C();. This way it makes it clear that you want an A interface, not a C implementation. Later when you change your mind, you can safely change it to A a = new Another_Subtype_Of_A(); without breaking other code.
This is especially true when A is an interface(In your case, A is a class). For example, if you just want a list, List list = new ArrayList(); is clearly better than ArrayList list = new ArrayList();. That's called "programming to interface, not implementation".
If you're creating an object that specifically needs C's interfaces(esp. those not present in A), you'd better choose C c = new C();. If you write A a = new C() instead, sooner or later you still have to cast the object to C(because A doesn't have all of your desired interfaces), so why bother?
It's not about the runtime type of the variable. You may only know you have a Vehicle object at compile time and based on user input, that may be a GarbageTruck or SportsCar.
GarbageTruck t;
...
t = new SportsCar(); //can't do this!
// so we do this:
Vehicle t;
if(user.isFast()) {
t = new SportsCar();
} else {
t = new GarbageTruck();
}
Java is all about Interfaces and Implementations.
An Interface is simply a set of public fields (methods & properties) the describe how users can interact with a class that implements the interface.
An Implementation is the code that actually makes those methods and properties do something. An Implementation can be a class that implements an interface, or it could be a subclass of some other implementation.
When you instantiate a class, you're writing code like:
Interface a = new Implementation();
Often times, we wrap the Interface and the Implementation all together... put another way, when we define a class, whether we're explicitly implementing an interface or not, we're defining an Interface with every public method we write.
Thus, it's the Interface that affects what methods we can call, but it's the Implementation that affects what happens when we call them.
firstly A is parent class and C is child class when you do A a = new A() then object of A is created and hold by A handle. When you do C c = new C() then object ofC is creating and C handle holds it.. But when you do A a = new C() then object ofC is created and Ahandle holds it. It means all the properties ofC is now been used. Although handle ofA is used by properties (instance) of C are used. This us polymorphism. Now it will used all the overloaded methods of C and not of A
Usages as an example
The difference come when you create a large project having methods created for child classes
Assume you have hello method
public void hello(C c) { }
In future you have another class B which extends A.. in that case you cannot use hello as its argument is of type C.. And imagine you have many classes as a child of A which need to use such method (then how many such methods you will create). Polymorphism is the rescue
You create hello with A as argument
public void hello (A x) { }
and now you can use same method for all the children of A..
A c = new C()
A b = new B()
Now all can use hello
this is the beauty of polymorphism
The question might be a very basic one. I am new to Java so please bear with me.
My code:
class A
{
int b=10;
A()
{
this.b=7;
}
int f()
{
return b;
}
}
class B extends A{ int b; }
class Test
{
public static void main(String[] args)
{
A a=new B();
System.out.println(a.f());
}
}
Why is the output 7? Doesn't class B get its own instance variable b?
It would but the function f can only see the version of b that is in A. Thus the function returns 7.
If you were to copy the function f into the class B you would see the member b of the class B being returned.
As Hiding instance variables of a class explains, Java variables are not polymorphic. The 2 b variables are 2 different variables as you would expect, but when you call the function A.f it can only see the one b variable that A has. So it returns A.b and NOT B.b.
So to answer your question, class B DOES get its own instance variable b, and it is completely independant of A.b but you currently have no way to access it so you cannot see its value.
Your type reference is A:
A a = new B();
Thus instance fields/static fields and static methods will be provided from A, as long as concerned method (in your case f()) isn't overriden by B.
In other languages, as Scala, variables can be redefined in subclasses and targeted even from a supertype reference.