I don't understand how exactly it works.
We have two class A and B. Class B extends A.
Class A have x attribute, and test method which modify this attribute.
Class B have x attribute, and test method which modify this attribute.
public class A {
int x;
public void test() {
this.x = 1;
System.out.println("A" + getX());
}
int getX() {return x;}
}
public class B extends A {
int x;
public void test() {
this.x = 2;
System.out.println("B" + getX());
}
int getX() {return x;}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();
System.out.println(a.getX());
System.out.println("point 1");
a = new B();
a.test();
System.out.println(a.x);
}
}
Output:
A1
1
point 1
B2
0
My prediction about last line of output was 2, but is 0. Why is 0?
Let's understand these lines of code:
a = new B();
a.test();
System.out.println(a.x);
You create a new object of B. It will re-initialize the variable - A.x = 0 and B.x = 0.
Then you invoke a.test(), which will call the overridden method test() in class B, which will set B.x to 2 using this.x = 2;. Note at this point, A.x is still 0.
Then you access a.x, which will access the field x in class A. The fields are not polymorphic. You don't override fields, but you hide them. The variable x in B hides the variable x in A.
If both A and B have a member named x, the one in B will block access to the one inherited from A. Remove the int x; declaration from B, or explicitly use super.x, if you want to reference the one in the parent class.
Starting from begin.
When you write
A a;
You say to JVM please reserve me in memory an address for something that fits A.
after when you do
a = new A();
You say to JVM, create a new object of class A and save the address to it under a
when you do this;
a.test();
You say to JVM, go to memory address a and from object there invoke method test().
Next thing what you do is this:
a = new B();
You say to JVM, create a new object of class B and save the address to it under a. No error here as B fits A as is a child class.
(You loose the connection with object of class A ass you changed it to B).
next operation is
a.test();
you also know this, but this time under address a is instance of class B. This time JVM search for the method in class B, if not fond then will search in class A.
I think you should start over with the Inheritance/Polymorphism concepts first.
But to make it clear: You have an object "a" which is declared as with type "A". Now, when you call the method test (which is overriden inside B in this case), the JVM calls the actual objects method. So, before "point 1" a.test calls A's test method, after "point1" it calls B's test method.
The problem is that this feature (called polymorphism) works only on methods. Whilst when you call an instance variable (as a.x) , the JVM calls the declared object variable. In this case is A. If you make a cast first, you'll get the right value: ((B)a).x
Note, the difference between actual and declared object is based on the type after the "new" operator (like new B()) and that in the object declaration
Related
I am curious why the last two prints generated different value?
class A {
int i = 1212;
}
class B extends A {
A a;
public B(A a) {
this.a = a;
}
}
class MainClass {
public static void main(String[] args) {
A a = new A();
B b = new B(a);
System.out.println(a.i);
System.out.println(b.i);
System.out.println(b.a.i);
b.a.i = 2121;
System.out.println("--------");
System.out.println(a.i); // 2121 ??
System.out.println(b.i); // 1212 ??
}
}
When I set "i" like this:
b.a.i = 2121;
I am accessing the same reference, it means the same Object A? Object A is created only once, so how is possible to set the variable on the object and get different result depends on the way how I access this value?
UPDATE:
Debug variables in IntelliJ
In IDE it seems that class B has it's own copy of "i" that is of course untouched by changing it via "b.a.i" because the change was made on the A object. Can you please arguing against this assumption because it is still in my head and IDE debug show to me that on the Object "b" there is an "i" variable.
Here the declaration of B is referring to A's object in two different way
inheriting A directly.
storing A as a property.
So B is having two different A.
Question #1: are you referring to the same A as inheriting?
Answer: no, by b.a.i you are not referring to the inheriting A, you are simply referring to property A
object A is created once this is true partially, actually you are creating another A by creating object of B.
To refer to the inheriting A you must use b.i
The Think is, int i = 1212 is the default value of all instances of A or it's children
when you modified the value for b, you modifies it only for that instance. So the other instances keeps it's default value.
One thing I would like to point out is that it is not typical to extend a class, and then create a reference to that class inside the child class.
When class B extends class A, that means that class B already has int i = 1212;. When you extend a class, you are essentially building on top of it.
So in your case, when you create a new A object, i = 1212. And then you create a new B object and pass in a, however, because class B extends A, it already has a variable called i that equals 1212.
Your print statements make sense:
a.i will be equal to 1212 because that is what the value is set to in Class A.
b.i will be equal to 1212 because B extends A and will inherit the variable i from Class A.
b.a.i will be equal to 1212 initially because you 1.) created an A object a, 2.) created a B object b that has it's own A Object variable that you set to a.
When you call b.a.i = 2121, you are setting your B object's variable a to have an i value of 2121. But remember that the object reference in your B object points to the first A object you created. Both a and b.a point to the same object in memory.
This question already has answers here:
Does polymorphism apply on class attributes in Java?
(8 answers)
Closed 4 years ago.
I have the following program :
class A{
int b = 50;
}
class B extends A{
int b = 20;
}
public class Maini{
public static void main(String[] args){
A a = new B();
System.out.println(a.b);
}
}
and the result is 50 and I would like to know why?
before I run the code I am pretty sure that the result should be 20.
This has nothing to do with how constructors work.
Note that the member variable b in class B does not override the member variable b in class A. Only non-static, non-private methods can be overridden. Member variables cannot be overridden.
If you have an instance of class B, then it actually has two member variables called b: one in the superclass (A) part of the object, and one in the subclass part (B).
The reason that you see the value 50, which is the value of b in the A part of the object, is because the variable a in the main method is of type A. If you change this to B, you'll get 20:
B a = new B(); // instead of A a = ...;
In the statement
A a = new B();
You are calling Bs constructor in an object of type A
In your program, you have given no constructor to B, so it looks to A.
In A, the value of int b is 50 and an object is of type A, hence the value is chosen as 50
If you had a constructor in B e.g.
B() { b = 20;}
the value would be 20.
You think that you are creating a B but you have not written any constrcutors for the class B so it looks to the super() constructor which is it's parents (A). So you now have an object of A. If you are curious about why A's object isi being created while there is no constructor to it too. A calls to it's super constructor too which is Java's Object Class's constructor.
I hope that I could make this point clear.
use a intellitrace enabled IDE for better experience of coding.
1st of all you'l hav a default constructor if you are not imposing on it.
Secondly you are defining an object of type 'A' not 'B'. if you want the output as 20 then you hav to include this B() {int b = 20;}.
Here in this code Sniplet there is no constructor in Any class.
So JVM will create no argument default constructor in all classes.
While you are Running this then .
In the below code you
a is referring class A and having object of class B
A a = new B();
So here the Object a will have class A 's variable value.
and Class B object value as its calling Class B 's default constructor(new B();)
If Class A and B have same Method like below Example:
class A{
int b = 50;
void method(){
System.out.println("Method of A class");
}
}
class B extends A{
int b = 20;
void method(){
System.out.println("Method of B class");
}
}
public class Maini{
public static void main(String[] args){
A a = new B();
System.out.println(a.b);
a.method();
}
}
Then a.method() will print
50
Method of B class
as a is have Class B 's object.
When you write A a = new B() the object a is type A. This is why you're getting b = 50. If you want to get b = 20, you need to declare a as a B class
Hope it's clear enough.
Best
In the code below, the instance variable called "x" inside subclass "B" hides the instance variable also called "x" inside the parent superclass "A".
public class A {
public int x;
}
public class B extends A {
public int x;
}
In the code below, why does println(z.x) display the value of zero? Thanks.
A a = new A();
B b = new B();
a.x = 1;
b.x = 2;
A z = b;
System.out.println(z.x); // Prints 0, but why?
In the code below, why does println(z.x) display the value of zero?
Because it's referring to the x field declared in A... that's the only one that z.x can refer to, because the compile-time type of z is A.
The instance of B you've created has two fields: the one declared in A (which has the value 0) and the one declared in B (which has the value 2). The instance of A you created is entirely irrelevant; it's a completely independent object.
This is good reason to:
Make all of your fields private, drastically reducing the possibility of hiding one field with another
Avoid hiding even where it's possible, as it causes confusion
So, I have these 3 classes in Java.
When I run the program I get:
20,
15,
10,
My question is, why do I get this instead of:
15,
20 (doesn't public int getX(); in class B get us to 15+5=20?),
10
for example?
Can you please explain to me , step by step, what really happens in this program because I am very confused with the output(and the sequence).
public class A {
private int x = 15;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void printX() {
System.out.println(this.getX());
}
}
Child:
public class B extends A {
private int x = 5;
#Override
public int getX() {
return super.getX() + x;
}
#Override
public void setX(int x) {
super.setX(x);
super.printX();
}
#Override
public void printX() {
System.out.println(super.getX());
}
}
and
public class C {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
This is happening because you instantiate a as a B object - A a = new B(). It doesn't matter that the explicit type of a is A; it's more generic (abstract) than its real type B (because B inherits from A), therefore polymorphism calls B methods (more specific) in first order. The same applies to fields.
After calling a.getX() class B references to A's getX(), which returns its 15 (superclass method has no reference to the object it was called from in this case), then 5 (B's x) is added, resulting in 20.
The subsequent calls behave in a similar manner.
I have given a basic example similar to your problem go through it you will get your answer. This is the concept of runtime polymorphism
Inheritance creates typecompatibility. It allows a super class reference to refer to the object of sub class. (Reverse is not true).
A super class reference, that refers to object of sub class, can only be used to access the inherited and overrridden methods of sub class. The members newly defined in sub class are not accessible using reference of super class.
class A
{
void f1()//this holds address of object of B
{
System.out.println("A f1");
}
void f2()
{
System.out.println("A f2");
}
}//A
class B extends A
{
void f3()//new method
{
System.out.println("B f3");
}
void f2()//this holds address of object of B
{
System.out.println("B f2 starts");
f3(); //this.f3()
System.out.println("B f2 ends ");
}
}//B
class TypeCmptbl
{
public static void main(String args[])
{
A ref; //reference of A
ref = new B();//Object of B
//ref.inherited() allowed
ref.f1();
//ref.overridden() allowed
ref.f2();
//ref.newMembersOfChild() not allowed
//ref.f3();
}//main
}
Consider the statement
ref.f2();
Here ref is a reference of class A and it has address of object of class B f2() is a overridden method.
When compiler detects such a statement then it doesn't bind the function call with any definition. It only validates the call.
Binding of such calls is left for the runtime environment. At program runtime system identifies the datatype of the object and binds the function call with the function definition provided by the class of object. This type of binding between the function call and function definition is called as "runtime polymorphism" .
Your question is related to the runtime polymorphism in java note that methods are bind at runtime, and the variables are bind at Compile time
In your example
public class C {
public static void main(String[] args) {
A a=new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
// reference is of A but the object is of B, so at runtime JVM see that memory is of B so the B's method is called, this is runtime Polymorphism
when the below statement is called , the getX() of class B is invoked.
System.out.println(a.getX());
#Override
public int getX() {
return super.getX() + x; // this will add 15 from class A + 5 in this method.
}
the above statement displays 20
when the below statement is called,
a.setX(10);
#Override
public void setX(int x) {
super.setX(x); // observe this method, this prints 15
super.printX(); // this prints 10
}
//super.setX(x); it will call
public void setX(int x) {
this.x=x; // 10 <--- 15 so 15 is displayed
}
here this.x refers the value which is passed through a.setX(10).
A a = new B();
So the concrete type of a is B.
System.out.println(a.getX());
You're calling getX() on an object of type B. So the following method is called, because the concrete type of a is B, and B has overridden the getX() method defined by A:
public int getX() {
return super.getX() + x;
}
It adds B's x (whose value is 5), with the result of super.getX(). This method, in A, is defined as
public int getX() {
return x;
}
So it returns A's x, which is initialized to 15.
The result is thus 5 + 15 = 20.
The rest can be explained the same way. Remember that fields are not accessed in a polymorphic way. Only methods are. So, inside the code of A, when you see x, it always mean "the value of the field x in A". Inside the code of B, when you see x, it always mean "the value of the field x in B".
When you say:
A a = new B();
it means Object of A is instantiated with class B. So, in the memory, a space is reserved for your object 'a' which contains all the methods and properties of class B (not A).
So, when the first print statement is executed, it executes the getX() method of the class B and not the getX() method of class A.
For other methods called by your object 'a', the methods of the class B are called.
This is also known as dynamic binding, as JVM allocates the memory to the object 'a' at the run time and not compile time.
For more details on dynamic binding check these links:
http://www.tutorialspoint.com/java/java_overriding.htm
http://www.tutorialspoint.com/java/java_polymorphism.htm
I also suggest you to instal eclipse on your machine and run your code in the debug mode.
This is the best way you can study your code.
In a situation like this:
class A{
public int x = 4;
public void s3(){
x = 3;
}
public void f(){
x = 8;
s3();
}
}
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
a.f() calls the f() of the class B, then f(), after an assignment, calls the s3() function. At this point, s3() is only defined in A and when it assigns the value 3 to x, x is the copy of the variable owned by the class A. Why s3() doesn't use the x declared in B? In theory, B shouldn't has its own copy of s3() function inherited from A? (so the s3() inherited from A in B should use the x declared in B)
You have a misunderstanding of what you should be doing in inheritance. extends is a reserved word that was wisely chosen. The point of B extending A is to say that B is a subset of A with additional attributes. You're not supposed to redefine x in B; A should be handling x. By redefining x in a subclass, you're hiding the superclass' field x (this is true even if x refers to different variable types).
A a = new B();
System.out.println(a.x); //4 makes sense, since we are of class A
B b = (B) a;
System.out.println(b.x); //5 makes sense, since we are of class B
a.f();
System.out.println(a.x); //3 makes sense, since a.f() calls s3(), which sets A's x to 3
System.out.println(b.x); //10
The 10 follows from printing b's x, which is assigned to 10 with the call of a.f(), which then calls s3() which is why the 3rd example prints 3. To see what I mean look at this:
public void f()
{
x = 10; //sets B's x to 10
s3(); //calls A's s3(), which sets A's x to 3.
}
Because it is the same. You do not have two copies ("instances") of the object, only one.
Since the one you create is a B instance (new B()), it will be used the methods as defined in B. Of course, when no methods are defined in B it will use the superclass methods implementation.
So, you only have an x attribute and s3 forces it to be 3. It works ok.
Why s3() doesn't use the x declared in B?
Generally, methods in a parent class cannot see member variables in a child class.
I think doing just this:
B b = new B();
b.f();
is enough to reproduce at least part of your confusion. Here is what f() looks like in B:
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
f() is equivalent to:
public void f(){
this.x = 10;
this.s3();
}
So calling b.f() means f() is equivalent to:
public void f(){
b.x = 10;
b.s3();
}
Next, what happens inside the s3() method in A? s3() looks like this:
public void s3(){
x = 3;
}
and that is equivalent to:
public void s3(){
this.x = 3;
}
'this' is the object that called the method, which from the last example of f() you can see is b. So s3() is equivalent to:
public void s3(){
b.x = 3;
}
So b.x gets overwritten with 3...uhhhhm not so fast!
An instance of B also inherits an x from A, it's just that inside B it so happens that B's x shadows the x from A. As a result, the f() method in B assigns to the x from B. Inside s3() however, the x that b got from A is not shadowed anymore, and as far as A is concerned there is only one x--the one from A. In other words, the lookup for b.x takes a different path depending on what class that statement appears in.
After s3() executes, the end result is that b has two x's with two different values. Inside methods in B, the x from B will be visible, and inside methods in A, the x from A will be visible. Inside methods in B, it is possible to get at the the x from A by using super.
In theory, B shouldn't has its own copy of s3() function inherited from A?
Don't think in terms of copies. Think in terms of pointers from class to class, and pointers from classes to lookup tables. Typically in computer programming, each instance has its own instance variables but methods are shared by all the instances in a class.