I have one interface I1 which defines a method M1. Two other classes C1 and C2 are implementing I1 and over-rides M1.
In another class C3 I have a reference to M1. Now how will I understand if M1 is referring to C1_M1 or C2_M1?
P.S I can find it out while debugging the code. But I am looking for some shortcut without executing it.
It is run time polymorphism so you are able to understand it at run time only.
If you know what will be the input to your program then you can understand which class instance reference came.
interface A{
}
class B implements A{
}
class C implements A{
}
class Main{
public static void main(String args[]){
// input
Object o = new B(); // just assume your logic give you object B.
if(o instanceof B){
B b = (B) o;
// invoke methods
}else if(o instanceof C){
C c = (C) o;
// invoke methods
}
}
}
In above code you are able to understand that class B methods will be invoked.
Summary of all is - you have to understand your code, recognize the inputs and then you are able to understand which class will be called at run time. otherwise debugging is best practice.
if you created object in this way
I1 i=new c1();
then i.m1() will call m1 method of class c1
if
I1 i=new c2();
then i.m1() will call m1 method of class c2
If you don't know how the object is created and you have only the reference then Sorry to Say you can only find it at runtime as it is Run time Polymorphism
Related
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.
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.
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.
So, I have this:
public class A {
public int a = 0;
public void m(){
System.out.println("A"+a);
}
}
And this:
public class B extends A {
public int a = 5 ;
public void m (){
System.out.println("B"+a);
}
public static void main(String[] args) {
A oa = new A();
B ob = new B();
A oab = ob;
oa.m();
ob.m();
oab.m();
System.out.println("AA"+oa.a);
System.out.println("BB"+ob.a);
System.out.println("AB"+oab.a);
}
}
Output:
A0
B5
B5
AA0
BB5
AB0
I don't understand why oab.m(); output is B5 instead of A0. Can someone explain this to me?
That's the whole point of polymorphism. The concrete type of oab is B (since the object was created with new B()). So the method B.m() is called.
Look at the Animal example in http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29 to understand why it's useful. When you have an animal, and this animal is a Cat, you expect it to say "Meow!" when you make it talk.
B ob = new B();
A oab = ob;
Similar as
A oab=new B();
I don't understand why oab.m(); output is B5 instead of A0
Because you creating object of B and referencing it to A so m() is being inherited and that's why B's version of m()is being called.
A oa = new A();
B ob = new B();
A oab = ob;
From the code above ob is an instance of class B. It can be stored in a variable of class A as A extends B. But as the stored Object instance is of B and hence it is not aware of A's m() function.
Hence the out put is B5
In inheritance actual method invocation depends on the type of the actual object and not on the type of the reference.
B ob = new B();
A oab = ob;
Here oab is a reference variable of type A but it is pointing to object of type B i.e. ob so at runtime oab.m() will invoke overridden m() method from class B
In Java there is something like late binding (polymorphism). It means that code of method is not linked while compilation time (early binding), but while runtime. While invoking oab.m(); JVM is checking actual type (class) of object from aob reference (in your case B) and based on that info invoking code of method from that class. That is why oab.m(); returns B5.
You also need to know that late binding works only for methods, not fields. For fields value will be determined by reference type, so oab.a will return 0 not 5.
Imagine you had the following:
public class C extends A {
public int a = 7 ;
public void m (){
System.out.println("C"+a);
}
Now if you had this in your Main method...
C oc = new C();
A oac = oc;
oac.m();
...you would want that last call to output the stuff that is specific for the class C.
The point is that B is an A, and C is an A, but each of them have more specific versions of the values that an A contains, and when you ask for those data, the specific versions of them should be returned.
Now you can do this:
// Get an instance of B or C, but you don't
// care which - could be either:
A someVersionOfA = getAnInstanceOfA();
// This works no matter if you've got an instance
// of B or C, but the result should vary accordingly:
someVersionOfA.m();
As someone else mentioned, think of A as "Animal", B as "cat", and C as "Dog". If m() means "Make some noise", then calling m() should result in "Meow" or "Woof!" depending on on the instance getAnInstanceOfA() returned.
You have just copied the internal address of B to A one, and replacing it.
B inherit from A, so no compilation problem.
Finally, the reference to A is destroyed, it is now a copy of reference to B
Please tell me why i am getting ClassCastException in this case
I have type casted , the source of B class to A as shown below , but why i am still getting ClassCastException here .
public class A extends B
{
}
public class B {
public String getData() {
return "B";
}
}
public class Main {
public static void main(String args[]) {
A a = new A();
B b = new B();
a = (A) b;
System.out.println(a.getData());
}
}
It becomes more obvious if we play with different classnames:
public class Car extends SomethingWithWheels {} // was A extends B
public class SomethingWithWheels {} // was B
public class Train extends SomethingWithWheels {} // aahh, some C extends B
Now, lets cast again:
SomethingWithWheels somethingWithWheels = getItFromSomewhere();
Car car = (Car) somethingWithWheels;
The compiler has to complain, because somethingWithWheels (B) could be a Train instance (C), which can't be cast to Car (A).
You can't cast a base class to derived class. You can do the other way round though.
Because your instance "b" is not of type A (B does not extend A), so when you cast "b" to A it fails.
The opposite would work (casting an instance of type A to type B)
Because an instance of B is not an instance of A. It's really that simple.
If you create an instance of A, it's also a B - because that's what the subclassing means. However, if you create an instance of B, that is not an A, and can't be assigned/cast as such.
The only time you can cast is if the run-time class of an object is compatible with the type you're trying to cast to. You can't change the class of an existing object - which is what I think you might be trying to do here - only tell the compiler "look, I know it's really something more specific".
So as a counter-example, the following would work:
public static void main(String args[]) {
B b = new A();
A a = (A) b;
System.out.println(a.getData());
}
In this case, the variable b is declared to hold a reference to a B. It turns out that you populate it with an instance of A, but for the rest of the program the compiler isn't allowed to assume that b is an A, because it's not guaranteed. Since you know it's an A in your specific case, you insert the cast, which causes a run-time check that the object actually is an A. This succeeds, and from that point on you can call methods specific to A on your a variable.
In this case however there is no reason at all to do any casting - there are no extra methods available on the subclass that you'd need to call, and no methods which only take an A but not a B. Even if A overrode getData to do something different, you would still get this behaviour if invoking through a B reference.
You are downcasting and you try to cast a supertype to a subtype, thats why it does well during compilation but fails at runtime with ClassCastException.
You can call:
System.out.println(a.getData());
after removing the line where you try to cast the types