In the following code, I don't understand why when a1.k() is called, this.x in class C returns 100 instead of 1. My understanding is that this refers to the current object, but the static type of the current variable a1 is A. So shouldn't this.x returns 1, which is the variable for A type?
I mean a1.x should return 1, right? Many thanks!
class A {
public int x = 1;
public String k() { return "A" + this.x; }
}
class B extends A {
public int x = 10;
...
}
class C extends B {
public int x = 100;
public String k() { return "C" + this.x; }
}
class TestABC {
public static void main(String[] args) {
A a1 = new C();
C c1 = new C();
System.out.println(a1.k());
}
}
When you call a1.k() you dynamically dispatch to the k method that is defined by the actual object whose reference is in a1. In this case, it is a C not an A or a B, and hence the k method is the override defined in C.
The static type (of a1 for example) is used for static resolution; e.g. resolving static methods, overload signatures, and fields. But for instance method invocation, the ultimate selection of the method to be invoked is dynamic.
I know the k() in class C should be called, instead of the k() in class A. But why this.x returns 100? I thought the instance variable is bounded to the static type.
Well it is. But it is the static type that determines which x is used by this.x in the k() call is the static type of this in the C.k method body!
This feature is called Dynamic Polymorphism. The methods being called is not dependent of type of its declaration but by the type being assigned to it (definition).
For this the classes must inherit and also override the methods in the parent class.
Here C,B extends A and overrides the method k;
if you try to call some C specific methods or variable it will throw error. (Since A doesn't know about that)
A is holding reference to C (pointing to C)
a1.k is actually C constructed Object and its new C().k() where x is 100 in C.
class Base{
int x=10;
public int getx(){return x;}
}
class Sub extends Base{
int x=100;
public int getx(){return x;}
}
class Test
{
public static void main (String[] args)
{
Base b = new Base();
Sub s = new Sub();
System.out.println("sub: getx:"+s.getx()+" .x:"+s.x+" Class: "+s.getClass().getName());
System.out.println("base: getx:"+b.getx()+" .x:"+b.x+" Class: "+b.getClass().getName());
Base btoS = new Sub();
System.out.println("btos: getx"+btoS.getx()+" .x:"+btoS.x+" Class: "+btoS.getClass().getName());
}
}
Results in
sub: getx:100 .x:100 Class: Sub
base: getx:10 .x:10 Class: Base
btos: getx100 .x:10 Class: Sub
Since you declare a1 as new C(), a1 will be seen as an object instance of class C, which overrides the fields of its parent class B and A. So why you would do things like A a1 = new C(); (or you might see a lot of such implementation), there is a recommendation saying "programming to interface rather than the actual implementation.", and I think this explains better.
Related
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
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 have a class with multiple subclasses:
class A {
static int i = 5;
}
class B extends A{
static int i = 6;
}
class C extends A {
static int i = 7;
}
I'm trying to write a comparator that takes two A's and compares them based on their values of i. I'm stuck at:
public int compare(A a1, A a2) {
}
Neither a1.i nor a1.class.getField("i").getInt(null); work.
How can I get the value of the static field from the object?
a1.i
Because a1 is declared a A, it is equivalent to A.i. The compiler should tell you about that with a warning. Most IDE will do that to and give a little message about what to do about it.
a1.class.getField("i").getInt(null);
Can't work because class is static.
You can use
a1.getClass().getDeclaredField("i").getInt(null);
getClass is an instance method to get the class of an object. getDeclaredField will return all fields, while getField will only return the public ones.
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 this code I allocate one only object, but in some way I store 2 copies of x (one for the base class and one for the subclass). How is it possible if the object is only one? Where is the space found to store two x vars? Does it mean in reality two objects are createed?
class App {
class Base {
public int x;
public Base() {
x = 2;
}
int method() {
return x;
}
}
class Subclass extends Base {
public int x;
public Subclass() {
x = 3;
}
int method() {
return x;
}
}
public static void main(String[] args) {
new App().run();
}
public void run() {
Base b = new Subclass();
System.out.println(b.x);
System.out.println(b.method());
}
}
One x belongs to the superclass and the other to the subclass. The fact that they have the same name is of no importance and you can access both by qualifying your access expression with the class:
((Base)b).x
((Subclass)b).x
(note that the cast in the first line is not necessary; I've put it in for symmetry)
In java you can not overload variables.,Though they are with the same name,their classes are different.
According to this tutorial(in section "What You Can Do in a Subclass"), when you declare a field in the subclass with the same name as the one in the superclass, in this case x, the one in the superclass will be hidden, which means that there're actually two xs in the subclass, one for itself, the other for its superclass, only baring the same name x. You can reference to the one in the derived class using derivedObject.x and the one in the subclass using ((Base)derivedObject).x(or super.x if within the derived class)