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.
Related
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
I'm learning Java and I'm doing this exercise and I have to say what the main method prints. Its goal is to better understand Java inheritance.
interface X extends Remote{
A m(B bb) throws RemoteException;
}
class A implements Serializable{
int a;
A m(A aa){
aa.a = 3;
System.out.println("A.m");
return aa;
}
}
class B extends A{
int b;
A m(B bb){
bb.b = 7;
System.out.println("B.m");
return bb;
}
}
class C extends A implements X{
public B m(B bb){
if(bb.b == 7) bb.b = 9; else bb.b = 1;
System.out.println("C.m");
return bb;
}
}
Now I have a main method in which I call:
X x = new C();
B b = new B();
(x.m(b)).m(b); // prints C.m() A.m()
The third line of my main method, prints "C.m() A.m()" but I don't understand why it prints A.m(). The x.m(b) returns an object that has both static and dynamic type == B; on this object it is invoked m(b) method; so why it is not called the m() method of B class?
I've seen that the m() mehtod in B class is not an overriding of the m() method in A class because they have different explicit parameter.
thanks in advance
b in an instance of B, which extends A. As such, B has 2 m methods.
To know which is called, what is important is the type of the object on which the method is called.
(x.m(b))
is the result of the call to the m method from the X interface, because the declaring type of x is X.
Therefore (x.m(b)) is an object of type A (even though the actual implementation is a B).
This being a type A, the m method from the A class is called.
If you change the names of the methods, it will become clearer that the m methods from A and B are really different objects.
Your mistake is assuming that
The x.m(b) returns an object that has both static and dynamic type == B;
Which is wrong, because x is declared of type X, making the result of x.m a type A.
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
I have the a problem with the following four classes:
class X {
void a() {
b();
c();
}
void b() {
System.out.println("b from class X");
}
private void c() {
System.out.println("c from class X");
}
}
class Y extends X {
void b() {
System.out.println("b from class Y");
}
}
class Z extends Y {
void b() {
System.out.println("b from class Z");
}
void c() {
System.out.println("c from class Z");
}
}
public class Main {
public static void main(String[] args) {
Y y = new Z();
y.a();
}
}
Please don't comment reasonability of the classes, it's just an example. I also tried to follow the flow of the JVM through the methods using the eclipse debugger, but the steps throught the methods are at some points a bit to fast.
I already got, that
Y y = new Z();
creates the new instance of the Z class and assign it to a reference of the Y class. Since there is no constructor in Z, the compiler looks in each superclass whether there is an constructor, and in case there isn't one, it uses the constructor of the object class.
After that the
y.a();
method is called. There is no such a method in class Z, so again we end up at class X where method a exists and execute it.
First we execute method b which, because your object is an instance of class Z, and the method b is overwritten in class Z leads to the output
b from class Z.
After that the method c is called (in method a). Since our instance is still an instance from class Z and there exists a method c in this class you could come up with the idea that the output
c from class Z
will occur. But this is no true, because the c method in class X is a private method. Since it's private it can't be inherited to subclasses (it even can't be seen). So there is no need that any class inheriting from X also has the c method. Is it true, that because of that the call of c from method a leads to a call to the c method in class X rather than in class Z?
So recapitulating:
Is my explanation from above correct or am I missing anything? I just a little bit confused, that although my instance is from class Z, calling method c from inside method a leads to the following result:
b from class Z
c from class X
My first idea was that the output looks like:
b from class Z
c from class Z
Hopefully I described the problem in a way somebody can help me now. Thank you for all replies.
It is true that this will be printed:
c from class X
because c is private in X, and private methods aren't inherited in Java.
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
So, even though X's method a calls the c method, it can only call the c method in X. The presence of another method called c in Z doesn't matter; a can only call the c method in X. The c method in Z does not override the c method in X, because it's private.
The only way to call the c method in Z is to have a Z reference and to call it directly, because it's not private.
Z z = new Z();
z.c();
which will print
c from class Z
Yes you are right. In class X in method a():
void a() {
b();
c();
}
Only method c() from class X is visible. It's because from inside class X, class Z cannot be seen.
the compiler can resolve statically that c() its a private method inside de X class, there is no need to dynamic resolution and this implies that there is no polymorphic behavior for private methods.
Thinks in c() as a part of the implementation of a(), its a implementation detail, imagine for a moment that you change the name from c to c1 inside X, ¿you expect a different behavior for changing a private method name in a class?, the language must ensure that a change like that don't have effect on the children.
I ran into this example about inheritances on the web, and I am not easy regarding its results. I'm missing something critical.
public class A {
int i = 5;
public A() {
foo();
}
private void foo() {
System.out.println(i);
}}
public class B extends A {
int i = 6;}
public class C extends B {
int i = 7;
public void foo() {
System.out.println("C's foo");
System.out.println(super.i);
}}
I'm trying to figure out what's happening by the following command: C c = new C();
System.out.println(C.i);
I know that when we create a new instance of C we approach A's and B's constructures, So We reach to A() - (question 1) Does i (of A) being initialize on the way?
Now we need to call to foo()- (question 2)- Does C's foo() consider as an override of A's foo()? and what if B had a foo() of itself? then it was consider as a override and C's foo() was operated?
As far as I know, there is no override when it relates to local variables. How come that System.out.println(c.i) is 7 and not 5? shouldn't it b the i of the highest-father?
EDIT: My question is not about which foo and i will be used when I use c, is about what happens during these two specific commands, cause obviously A's foo was used and not C's.
Thank you very much.
The three i variables here are completely independent. Which one is used by any statement is determined at compile-time - there's no polymorphism involved. So A.foo() will always print out the value of the variable declared in A.
Note that these aren't local variables by the way - they're instance variables.
When you print out c.i that uses the variable declared in C because the compile-time type of c is C. You can see this if you write:
C c = new C();
A a = c;
B b = c;
System.out.println(a.i); // 5 - variable declared in A
System.out.println(b.i); // 6 - variable declared in B
System.out.println(c.i); // 7 - variable declared in C
Note that in a well-written program this sort of thing almost never causes a problem, as variables should be private.
No, you always use the the class member closest to the class you've instantiated. So, C c = new C(); will use i=7 and C's foo only. Class B's i is overridden by class C's i, just as A's i has been overridden by B's i.
There's no chaining going on, just overriding.
A, B, and C each have an instance variable called "i". If you have a C object and execute foo() you will print C's value for "i".
If you had put foo() in B rather than C, oddly you'd still get C's value for "i" if you have a C object, since the "outermost" version of "i" will be used.
About method overriding and visibility:
A.foo() is private. It means it's not visible to its subclasses. If you want B or C to override A.foo(), A.foo() needs to be protected or public. So in your code, B.foo() doesn't exist, because B doesn't know about A.foo().