consider the code below :
class B
{
int j =100;
}
class A extends B
{
int i=10;
}
public class Test
{
public static void main(String[] args)
{
A obj =new A();
System.out.println(obj);
B obj1 =obj;
System.out.println(obj1); // here i am confused
if( obj1 instanceof A )
{
System.out.println("yes"); //here i am confused
}
}
}
here the output is :
A#35186a
A#35186a
yes
Now obj1 is an instance of class B which is superclass , so why does the toString() show it to be object of A ? Also how can instanceof operator show it to be instance of class A ?
You have to distinguish between the reference and the actual object.
B obj1 = obj;
Here you create a new reference of type B named obj1. The object referenced is still an A object though, this can never be changed.
obj1 is pointing at obj which is an instance of A (see the new A()) you have got there. On the left hand side you are just referencing the super class. Your obj1 will only be able to see methods in B. obj will be able to see all methods in B and A (subject to correct access)
From the java trail
Declaration: The code left of the = associates a variable name with an object type.
Instantiation: The new keyword is a Java operator that creates the object.
Initialization: The new operator is followed by a call to a constructor, which initializes the new object.
There isn't any toString method in your code, you print the memory place holders (Java don't allow you to see the exact location of the object in the memory).
When you do "extends" you say "A is a son of B",then in the lines:
A obj =new A();
System.out.println(obj);
You create an A object and print is memory place holder (remember, A is son of B, so if you want to describe it, imagine a box called A and a box called B connected to her (on top of her, because it's her father)).
Now in the next lines:
B obj1 =obj;
System.out.println(obj1); // here i am confused
You create another object called obj1 and you assign him the memory place holder of A so, it's the first object that you created, called obj. how can you assign A object to a B? Polymorphism!1 and again you print it's memory place holder.
Next you do if:
if( obj1 instanceof A ){
System.out.println("yes"); //here i am confused
}
So, obj1 is an instanceof of A (it's a box of A and on top of her is a box of B (it's father, polymorphism)), and you print "Yes".
In polymorphism you print the lowest method, so you print the A methods if there is any, and if there isn't you "climbing up" to the father and check there and so on..
Polymorphism (computer science)
Now obj1 is an instance of class B which is superclass
That is not true, obj1 is still an instance of A. You just happen to assign a pointer of the super class to an already existing pointer of class A.
If you want an instance of class B just do this:
B b = new B();
If you want an instance of class A you can do this:
A a1 = new A();
or
B a2 = new A();
The later, a2, is correct because A is of type B. However, a2 is still an instance of A, because we used new A().
Related
Consider the following outline of code:
class B {
int a = 0;
void method1() {
// code
a = a + 1;
}
}
public class A extends Thread {
static B obj1;
public void run(){
obj1.method1();
}
public static void main(String args[]){
obj1 = new B();
A a1 = new A();
a1.start();
A a2 = new A();
a2.start();
}
}
Now, since a1 and a2 are two different objects, shouldn't the value be 1 while printing the value of a?
What am I missing?
How is the global reference for B working? I'm a little confused.
This code should produce compilation error.
How is the global reference for B working?
It doesn't. obj1 (type class B) is a non-static member of class A. The main method is static and not really running in context of any class A object. For this reason, the main function (static function) cannot access obj1 directly.
obj1 = new B();
In the above line, there is no actual memory of obj1 to store the reference created by new B(). Two different memory for obj1 are created as part of a1 and a2, which need to accessed as a1.obj1 and a2.obj2. Thus, no kind of global reference is created.
What you might be trying to do can be achieved by making obj1 as static.
static B obj1;
This can make obj1 act as a global reference as its memory is not part of any class A object. This will make both threads update same variable making value of obj1.a as 2 (not necessarily as the code isn't thread-safe).
I am a bit confused about how this code works can you help. I am trying to understand it in deep. So please feel free to refer any links for depth understanding about the subject matter.The output is A B B A
public class RuntimePolymorphism {
public static void main(String[] args) {
A a = new B();
B b = new B();
System.out.println(a.c + " " + a.getValue()
+ " " + b.getValue() + " " + b.getSuperValue());
}
}
class A {
char c = 'A';
char getValue() {
return c;
}
}
class B extends A {
char c = 'B';
char getValue() {
return c;
}
char getSuperValue() {
return super.c;
}
}
Actually, it's an interesting question ;), by the code, from the fist sight, I would say, it should output A A B A, yet it producing A B B A.
Then, I found a possible typo (or it was intentional, don't know):
A a = new B();
B b = new B();
we have two B's here, but we are also doing a type casting at the moment of instantiation of a variable. Even if we make c field as public it still produces the same result.
But, on the other hand, if we'll update to code like this:
A a = new A();
B b = new B();
everything will be as expected: A A B A.
Interesting finding: if we remove overloaded getValue() from the B class, the output will be A A A A...
Final conclusion: we can inherit a non-private field (that's we can access it from derived class), but we can't "overload" it the way we do with methods.
Thus, in Java, polymorphism is only working with methods and not with the fields.
The instance variable C from A is simply hidden in B
– A.C is ‘A’ because it's set in the class A
– A.getValue() returns ‘B’ because the object is of type B
So I think we should first understand the difference between Hiding and Polymorphism.
When you declare a subclass with a variable name the same as the superclass variable, then the subclass variable just hides the superclass variable.
For Runtime Polymorphism, a subclass method would need to override a superclass method. When a method in a subclass has the signature ( name and parameters ) and same return type as a method in its superclass, then the method in the subclass overrides the method in the superclass.
Another important point is that Polymorphismm ( Runtime in this case ) acts on methods that are evaluated at run time. But the initialization of values to the variables happens at compile time.
So, when A a = new B(); is executed, a's instance variable c has the value 'A'. So even if the reference a is pointing to a B object, the instance variables it refers to would be that of A.
Hence the output when we run a.c would be A.
But since the method getValue() is overriden in the subclass, a would call the overriden method ( because it is pointing to the subclass B object ).
Hence the output when we run a.getValue() would be B
So, when B b = new B(); is executed, b's instance variable c has the value 'B'. And this hides the variable c of the superclass. And if we want to refer to the immediate superclass's instance variables then we access it via super.<variable_name> So even if the reference a is pointing to a B object, the instance variables it refers to would be that of A.
The reference b is pointing to an object of type B and hence it would call B's getValue() method.
Hence the output when we run b.getValue() would be B.
As discussed above, we access the immediate superclass's instance variables via super.<variable_name>
Hence the output when we run b.getSuperValue() would be A
i want to make sure that my understanding is correct in static-polymorphism
please look at the code below
class a {
int x=0;
}
class b extends a {
int x=4;
}
public class main4 {
public static void main(String[] args) {
a f = new b();
System.out.println(f.x);
b ff = new b();
System.out.println(ff.x);
}
}
the output is
0
4
does that happened because the compiler looks at the declared type of the reference and upon that determines which x to print at compile time ??
(f is declared as type a, the compiler looks at f.x and decides it means a.x)??
& if so,is this called a static-polymorphism or hiding or what ??
thanks in advance
Polymorphism is like looking on the object via the key hole. You don't see the whole object but only that it's part which corresponds to the type of variable you have assigned a reference to the object to.
The object can be seen as different "shapes/forms" - it depends what the key hole you are looking through. But it is still the same object in computer's memory. The form you can see depends on the type of variable you have assigned the object to.
Polymorphism is a multi-form of seeing same object.
If you have object created by new b() - you'll see it as a b class representant when you assign this object to the variable of type b. And you'll see it as a a class representant when you assign it to the variable of type a.
But it is still the same object. And... you can cast it between variables:
f = (a)ff;
and you'll see that suddenly the same object is seen as an representative of a class (including visibility of x field belonging to the a class).
I was just trying some sample code for checking class variable overriding behavior in Java. Below is the code:
class A{
int i=0;
void sayHi(){
System.out.println("Hi From A");
}
}
class B extends A{
int i=2;
void sayHi(){
System.out.println("Hi From B");
}
}
public class HelloWorld {
public static void main(String[] args) {
A a= new B();
System.out.println("i->"+a.i); // this prints 0, which is from A
System.out.println("i->"+((B)a).i); // this prints 2, which is from B
a.sayHi(); // method from B gets called since object is of type B
}
}
I am not able to understand whats happening at these two lines below
System.out.println("i->"+a.i); // this prints 0, which is from A
System.out.println("i->"+((B)a).i); // this prints 2, which is from B
Why does a.i print 0 even if the object is of type B? And why does it print 2 after casting it to B?
i is not a method - it's a data member. Data members don't override, they hide. So even though your instance is a B, it has two data members - i from A and i from B. When you reference it through an A reference you will get the former and when you use a B reference (e.g., by explicitly casting it), you'll get the latter.
Instance methods, on the other hand, behave differently. Regardless of the the type of the reference, since the instance is a B instance, you'll get the polymorphic behavior and get the string "Hi From B" printed.
Even though A is initialized as new B(), the variable is an A. if you say
B a = new B();
you won't have that problem.
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