質問

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();
    }

}
役に立ちましたか?

解決 2

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" .

他のヒント

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.

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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top