How does instance field inheritance work in this particular code?

class A { int a = 2, b = 3; public void display() { int c = a + b; System.out.println(c); } } class B extends A { int a = 5, b = 6; } class Tester { public static void main(String arr[]) { A x = new A(); B y = new B(); x.display(); y.display(); } } 

Why does the output come out as 5.5? And not 5.11 ?. How does the y.display() method y.display() ?

+44
java inheritance
Jan 27 '14 at 10:01
source share
9 answers

Why is the conclusion 5.5?

Because A.display() knows only about the fields Aa and Ab . These are the only fields that any code in A knows about. It looks like you expect the ads in B to "override" existing field declarations. They do not do this. They declare new fields that hide existing fields. Variables do not behave almost like methods do - the concept of overriding a variable simply does not exist. From JLS section 8.3 :

If a class declares a field with a specific name, then declaring this field is said to hide any and all available field declarations with the same name in superclasses and superinterfaces of the class.

You can get the desired effect by changing B so that its constructor changes the values ​​of the existing fields that it inherits from A :

 class B extends A { B() { a = 5; b = 6; } } 

Note that these are not variable declarations. These are just tasks. Of course, in most codes (well, in most cases, I still saw) the fields in A would be private, so access to them from B impossible, but this is just an example to explain the behavior of the language.

+109
Jan 27 '14 at 10:08
source share

In class A you declare fields A and b . The display method uses these fields. In class b you declare NEW fields with the same name. You actually hide the old fields without overriding them. To assign different values ​​for the same fields, use the constructor:

 class A { A(int a, int b) { this.a = a; this.b = b; } A() { this(2, 3); } int a,b; public void display() { int c=a+b; System.out.println(c); } } class B extends A { B() { super(5, 6); } } 
+16
Jan 27 '14 at 10:12
source share

Wherein:

 class B extends A { int a = 5, b = 6; } 

you do not override a and b , you create new variables with the same name. Thus, you get four variables ( Aa , Ab , Ba , Bb ).

When you call display() and calculate the value of c , Aa and Ab will be used, not Ba and Bb

+13
Jan 27 '14 at
source share

There is something called variable override. That is why you get the same result in both cases.

+9
Jan 27 '14 at 10:11
source share

The reason is that Java uses the concept of the lexical domain to resolve variables.

In essence, there are two possibilities for solving free variables in a function (“free” means not local and not tied to function parameters):

1) against the environment in which the function is declared

2) against the environment in which the function is performed (called)

Java goes the first way, therefore free variables in methods are resolved [statically, at compile time] in relation to their lexical area (environment), which includes:

  • method parameters and local variables of the method
  • field declarations in a class containing a method declaration
  • open field declarations in the parent class
  • etc., up the inheritance chain

You will see that this behavior is implemented in most programming languages, as it is transparent to developers and helps prevent errors with variable shading.

This is the opposite of how methods work in Java:

 class A { public void foo() { boo(); } public void boo() { System.out.println("A"); } } class B extends A { @Override public void boo() { System.out.println("B"); } } class Main { public static void main(String[] args) { B b = new B(); b.foo(); // outputs "B" } } 

This is called a dynamic dispatcher: a method call is dynamically resolved at run time against the actual object on which it is called.

+6
Jan 27 '14 at 10:46
source share

When you compile your code, it pretty much becomes the following:

 class A extends java.lang.Object { int a=2,b=3; public void display() { int c=a+b; System.out.println(c); } } class B extends A { int a = 5, b = 6; public void display() { super(); //When you call y.display() then this statement executes. } } class Tester { public static void main(String arr[]) { A x = new A(); B y = new B(); x.display(); y.display(); } } 

And therefore, the superclass method class A called.

Now go to class A method. Here int c = a + b; means c = this.a + this.b; which is 2 + 3.

And the result is 5.

+5
Jan 27 '14 at 10:13
source share

Class B declares variables in scope B , public void display() is part of class A and knows only its own scope variables.

+2
Jan 27 '14 at 10:11
source share

This is the inheritance functionality, which gives 5,5 output.

+1
Jan 27 '14 at 10:22
source share

Java has nothing like overriding a variable. Thus, when calling the display () method, it refers to the variables inside the parent class "A", and not to the variables inside the subclass "B".

This can be explained for the same reason why you cannot print a variable declared in a subclass (and not in a superclass) inside the superclass method. The superclass method simply does not have access to the subclass variables.

However, you can print 5.11 if you have access methods for the fields of both classes, and you use these access methods to get values ​​instead of direct access using variable names. (even if the display () method is only present in the superclass). This is due to the fact that overridden access methods are called (in the second case), which return values ​​from the subclass.

0
Apr 25 '17 at 13:25
source share



All Articles