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
Related
I have a class A and a class B which extends class A
class A{
protected String x = "";
Method (){
x = "val";
}
}
class B extends A{
// Uses x in a method
}
If I write Junit test case for a method in class B, I get value of x as an empty string "" as set while declaration. Is there a way to set the value for x to "val" while testing class B method?
Given the new scope of the question, you should be able to set x by creating an object of type B (bObject) then calling Method() from A.
B bObject = new B();
bObject.Method();
This would set X given the methodology you show in your question. You could also say
B bObject = new B();
bObject.setX(str);
Where str represents whatever you want x to be for your test case. This assumes you have x set up with a getter and setter in A, which is generally best practice.
I come to you with a simple OOP question.
Let's say there are three classes - A, B and C.
B and C both inherit a static variable from A. Let's also say that A defines the value of this variable as being 0.
Let's say that both B and C modify the value of this static variable.
My question is this - since static variables remain constant across members of the same class, does this mean that setting the value of a variable of a superclass from a subclass will have no effect on the value of the super class?
In other words, if we change the value of B's variable to 1, that value will only be 1 for objects of class B and not C or A?
A static field only belongs to one class and is not inherited by its sub-classes
Here you can find simple java implementation for your problem.
The results can interpret solution.
class A {
static int variable = 0;
}
class B extends A{
}
class C extends A{
}
public class Runclass {
public static void main(String arg[]){
A a = new A();
System.out.println("A "+a.variable);
B b = new B();
System.out.println("B "+b.variable);
C c = new C();
System.out.println("C "+c.variable);
b.variable=1;
System.out.println("After modifying B "+b.variable);
System.out.println(" A "+a.variable);
}
}
Output:
A 0
B 0
C 0
After modifying B 1
A 1
static doesn't mean constant. final means that you can't change the value.You can reach the variable in the superclass A and change it, using this code for example in B: A.someVariable=1;After this, you will see the value 1 from C, B and A too, if you use the superclass A variable (A.someVariable).I give you a code example:
package teszt;
class A {
static int statValami=0;
}
package teszt;
class B extends A{
void writeOut(){
A.statValami=1;
System.out.println(statValami);
}
}
package teszt;
class C extends A {
void writeOut(){
A.statValami=100;
System.out.println(statValami);
}
}
package teszt;
class Over {
public static void main(String args[]){
new B().writeOut();
new C().writeOut();
System.out.println(A.statValami);
}
}
OUTPUT is:1100100
class A{
int foo=10;
}
class B extends A{
int foo=10;
}
class Test{
public static void main(String [] args){
A a=new B();
System.out.println(a.foo);
//System.out.println(a.getClass());
}
}
In this case 10 is output. If I am not wrong, then this is because the a variable is of type A and variable assignment is static binding, and static binding is done at compile time by looking at the type of the variable. Since here a is of type A, then A's int foo is called. However when I call
System.out.println(a.getClass());
then this gives class B, that is a is of type B. I am confused about this. Kindly explain to me a is of which type and how A's int foo is printed.
But by looking at this code
class A{}
class B extends A{}
class Test{
public static void main(String [] args){
B b=new B();
A a=b;
B b1=(B)a; // compiles and run fine (a is of type B)
}
}
How is this possible? What's happening here? First b is of type B then in the second line a becomes of type A, as A a=.. is written but a.getClass() gives that it is of type B. How? If a is of type B then why is it calling A's int foo in the first example? Kindly explain both examples.
Also, does type casting change references or do any other stuff?
An important thing to realise is that Java only has primitive and reference variable types. This means when you write
A a =
The a is just a reference to an object (or null) not an object.
When you do
A a = new B();
there is no cast here, no work is done, no object is harmed or changed.
When you call an instance method on a class, it calls the method for the class of the object.
Object o = new B();
assert o.getClass() == B.class;
a longer example
B b = new B();
A a = b;
assert a == b; // always true as they point to the same object.
assert b.getClass() == B.class;
// so it makes sense that since a == b
assert a.getClass() == B.class;
type casting change references or do any other stuff?
It changes the type of the reference and it doesn't do other stuff like change the type of the object.
methods follow inheritance, however fields follow the type of the reference as a field cannot be overridden, it can only be hidden.
B b=new B(); A x=b; B b1=(B)x; // compiles and run fine (x is of type b) in this line when x is of which type
correct and you wouldn't be able to (B)x unless x was a reference to a B The variables x is an A which means it must point to an A object or a sub-class of a A e.g. B you can write
B b = new B();
A x = b;
assert x == b; // they still point to the same object.
B b1 = (B) x;
assert b1 == b; // same object
assert x == b1; // same object.
No new objects are created, nor is the object changed.
Quite simple why it does print the foo of A, because a is defined as A. Since there is no overriding for variables you are simply accesing the variables which are accesible for the type the variable is declared, which is A in this case.
public static void main(String[] args) {
A a = new A();
System.out.println(a.foo); // prints the foo of A, since a is of the type A
A b = new B();
System.out.println(b.foo); // prints the foo of A, since b is of the type A
B c = new B();
System.out.println(c.foo); // prints the foo of B, since c is of the type B
}
In the end it´s called shadowing what you are doing there. Your class B has a variable with the same name as A. Since they are not overridable you are able to hide foo of A, if your variable is of the type B, where you are accessing foo of B
Your question is related to Javas polymorphic behavior and dynamic (late) vs. static (early) binding.
The access to all the member variables in Java follows static binding. That means you have no polymorphism in this case. Instance Methods are dynamically bound. The instance method used for an invocation will be determined by the class of the object, not by the reference type. For example:
public class Main {
static class A{
String foo="A";
public String getFoo() {
return foo;
}
}
static class B extends A{
String foo="B";
#Override
public String getFoo() {
return foo;
}
}
public static void main(String[] args) throws Exception {
A a=new B();
System.out.println(a.foo); // prints A
System.out.println(a.getFoo()); // prints B
System.out.println(a.getClass()); // prints Main$B
}
}
Late binding
Early Binding
Polymorphism
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
class A{
int a=10;
public void show(){
System.out.println("Show A: "+a);
}
}
class B extends A{
public int b=20;
public void show(){
System.out.println("Show B: "+b);
}
}
public class DynamicMethodDispatch {
public static void main(String[] args) {
A aObj = new A();
aObj.show(); //output - 10
B bObj = new B();
bObj.show(); //output - 20
aObj = bObj; //assigning the B obj to A..
aObj.show(); //output - 20
aObj = new B();
aObj.show(); //output - 20
System.out.println(bObj.b); //output - 20
//System.out.println(aObj.b); //It is giving error
}
}
In the above program i'm getting Error wen i try invoking aObj.b.
1.why i'm not able to acess that variable through the aObj though it is refering to class B??
2. why i'm able to acess the method show()?
You have to distinguish between the static type of aObj and the runtime type of aObj.
Code such as
A aObj = new B();
results in an aObj variable with static type A and runtime type B.
The compiler will only bother too look at the static type when deciding what to allow or not.
To your questions:
1.why i'm not able to acess that variable through the aObj though it is refering to class B??
Because there is (in general) no way for the compiler to know that aObj will refer to a B object at runtime, only that it will refer to some form of A object. Since .b is not available on all A objects, so the compiler will think "better safe than sorry" and disallow it.
2.why i'm able to acess the method show()?
Because this method is available in all A objects (if it's not declared in the subclass, it is still inherited from A).
aObj is a local variable of type A. A has no member called b, that's only in your subclass B. If you want to use b, you need to declare a variable of type B, but of course you can only assign it instances of B (or subclasses if there are any).
A declares a method show(), but you override the implementation in your subclass B.
This behavior is known as virtual method invocation, and it is an important aspect of polymorphism in Java. You should have a look at this tutorial.
class A{ // class A has variable a and method show();
int a=10;
public void show(){
System.out.println("Show A: "+a);
}
}
class B extends A{ //class B inherits variables and methods of A.
// so class B has variable a, b and show(). Also, show is overridden by class B.
public int b=20;
public void show(){
System.out.println("Show B: "+b);
}
}
since A doesn't have variable b inside it, even when u are passing B to A, you still have A object which does not have variable b inside it. So, trying to access b will give you compile time error.
in case of show(), A and B both have this method, so what you are doing here is actually overriding it at runtime. This is nothing but Polymorphism. So since A already has method show(), and it is overridden later by B,
A a = new B();
a.show();
this will run the show() method of B at runtime.
Methods and fields have different polymorphic behaviour.
The method that will be called is the method of the run time type of the instance
aObj=new B(); //new B()
The field that will be called is the field of the type of reference that you declared
A aObj = new A(); // A aObj
The following would work even is there was no show() method in A.
aObj = new B();
aObj.show(); //calls B's show()