45
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 would the y.display() method work?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
user3239652
  • 775
  • 2
  • 9
  • 23
  • 3
    I do think this is actually a good question that I've never considered of. – TwilightSun Jan 27 '14 at 10:05
  • 2
    Refer to this link: http://stackoverflow.com/questions/685300/is-there-a-way-to-override-class-variables-in-java – TwilightSun Jan 27 '14 at 10:07
  • 7
    @Qadir - isn't that what he's trying to do by asking a question in the first place? It's hardly a "plz send teh codez" request. I had to think about it for a few minutes myself, and I have several years experience behind me. – Kirschstein Jan 27 '14 at 13:47
  • 1
    Is it that methods are virtual (in C++/C♯ language), and variables are not. Variables are accessed directly with no dereference. – ctrl-alt-delor Jan 27 '14 at 15:40
  • I had to test this PHP to see how did it go...aaaaaaaand it's 5,11 :) http://phpfiddle.org/main/code/3e9-3fg – Songo Jan 27 '14 at 15:40

10 Answers10

109

why does the output comes 5,5?

Because A.display() only knows about the fields A.a and A.b. Those are the only fields that any code in A knows about. It looks like you expect the declarations in B to "override" the existing field declarations. They don't. They declare new fields which hide the existing fields. Variables don't behave virtually in the way that methods do - the concept of overriding a variable simply doesn't exist. From the JLS section 8.3:

If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.

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

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

Note that these are not variable declarations. They're just assignments. Of course in most code (well, most code I've seen anyway) the fields in A would be private, so couldn't be accessed from B, but this is just example for the purpose of explaining the language behaviour.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
16

In class A you declare fields a and b. The method display uses these fields. In class B you declare NEW fields of the same name. You're actually hiding the old fields not "overriding" them. To assign different values to the same fields use a 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);
    }
}
fabian
  • 80,457
  • 12
  • 86
  • 114
14

When doing this:

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

you are not redefining a and b, you're creating new variables with the same names. So you end up with four variables( A.a, A.b, B.a, B.b).

When you call display() and calculate the value of c, A.a and A.b will be used, not B.a and B.b

Andy
  • 3,631
  • 2
  • 23
  • 32
9

There isn's anything called variable overriding. That is why you are getting the same result in both the cases.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Amit Sharma
  • 1,202
  • 11
  • 26
6

The reason is that Java uses the concept of lexical scope for variable resolution.

Fundamentally, there are two possible options to resolve free variables in a function ('free' means not local and not bound to function parameters):

1) against the environment in which the function is declared

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

Java goes the first way, so free variables in methods are resolved [statically, during compilation] against their lexical scope (environment), which includes:

  • method parameters and local method variables
  • field declarations in the class containing method declaration
  • public field declarations in parent class
  • and so on, up the chain of inheritance

You would see this behaviour implemented in most programming languages, because it is transparent to developer and helps prevent errors with shadowing of variables.

This is opposite to the way 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 dynamic dispatch: method call is resolved dynamically in runtime against the actual object, on which it is called.

5

When you compile your code it pretty much becomes like:

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 hence, when super calls, the method of class A is being called.

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

And the result is 5.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pulah Nandha
  • 774
  • 4
  • 23
2

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

ST3
  • 8,826
  • 3
  • 68
  • 92
1

It's the inheritance functaionality which gives the output 5,5.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Java doesn't have anything like variable overriding. Thus, when the method display() is invoked, it accesses the variables inside the parent class 'A' and not the variables inside the subclass 'B'.

It can be explained with the same reason of why you can't print a variable declared in a subclass (and not in superclass) inside superclass method. The superclass method simply doesn't have access to the subclass variables.

However, you'll be able to print 5,11 if you have accessor methods to the fields in both the classes and you use those accessor methods to get the values instead of directly accessing using variable names. (even if the display() method is present only in superclass). This is because the overridden accessor methods are invoked (in second case) which return the values from the subclass.

0

Why does the output come out as 5,5? And not 5,11?

Whenever we have same instance variables (applicable to class variable as well) in a class hierarchy, the nearest declaration of the variable get the precedence. And in this case, nearest declaration of a and b from display () method is A’s. So class B’s instance variables go hidden. Hence in both cases, 5 gets printed.

How would the y.display() method work?

Another alternative is to have getter in both classes to get value of a and b.

    class A
{
    int a = 2, b = 3;
    public int getA() {
        return a;
    }

    public int getB() {
        return b;
    }
    public void display()
    {
        int c = getA() + getB();
        System.out.println(c);
    }
}
class B extends A
{
    int a = 5, b = 6;
    public int getA() {
        return a;
    }

    public int getB() {
        return b;
    }
}
class Tester
{
    public static void main(String arr[])
    {
        A x = new A();
        B y = new B();
        x.display();
        y.display();
    }
}

Prints

  • 5
  • 11
Developer
  • 534
  • 1
  • 11
  • 21