2

I'm checking some Java exercises but I'm confused with this one:

We have a Foo class with this structure:

public class Foo {
    public int a = 3;

    public void addFive() {
        a += 5;
    }
}

A Bar class who inherits from Foo:

public class Bar extends Foo {
    public int a = 8;

    public void addFive() {
        a += 5;
    }
}

And a Test class :

public class Test {

    public static void main(String[] args) {
        Foo f = new Bar();
        f.addFive();
        System.out.println(f.a);
    }
}

I would think the output is 13, but it's 3, my question is Why?..

2
  • 1
    The line int a += 5; won't compile. I suspect you meant a += 5; to match the code in the superclass method, which needs a semicolon. Commented Dec 2, 2013 at 21:07
  • Yep that's right, I was copying on the fly .. thanks ! :D Commented Dec 2, 2013 at 21:34

5 Answers 5

7

Adding to Peter's answer : keep in mind that member variables are not polymorphic, so they are not overriden.
I.e. f.a still gives you reference to super class's a (since f's declared type is Foo) whereas f.addFive() calls method on Bar, (since f's runtime type is Bar);

So, for example

Bar b = new Bar();
Foo f = b;
f.addFive();
System.out.println(f.a); // prints 3
System.out.println(b.a); // prints 13 as you have expected

Hope it is clear.

Sign up to request clarification or add additional context in comments.

Comments

5

You have two fields, one which hides, not replaces the other. You have Foo.a and Bar.a You overridden method alters Bar.a but you are looking up Foo.a

1 Comment

Polymorphism doesn't apply to fields.
5

You need to know that in Java late-binding (mechanism of polymorphism that finds body of method based on actual object at runtime) works only for methods, not for fields.

So if you have reference of base type Foo that holds object of type derived from Foo like in our case Bar

Foo f = new Bar();

then with f.field you will use field from Foo class (no polymorphic behaviour here).
But if you use f.someMethod() then thanks to late-binding at runtime Java will find and execute code of this method from Bar class (since f holds insteance of Bar object).

So in your code

Foo f = new Bar();//you are creating reference of type Foo to instance of Bar
f.addFive();//body of this method will increment `a` declared in `Bar`
System.out.println(f.a);//here you are using `a` declared in Foo.

You can get value a from Bar class if you use reference of type Bar.

System.out.println(((Bar)f).a);//prints 13.

1 Comment

+1 for System.out.println(((Bar)f).a); Makes a good point too.
0

In your Bar#addFive() method, you declare a local int a. Changes to this local int a do not affect the class member int a. Since f is a Foo, the value of a will be 3 in this case.

Also, you do not need to redeclare your addFive() method in your Bar class since there is no difference from the Foo#addFive() method.

EDIT: Oddly, the code you originally posted has changed and the int a is now no longer local. What is the actual code you are using?

3 Comments

I think that was a typo as that wouldn't compile if it was written that way.
It will compile even if it is a typo.
It really won't, try it.
0

Because you are initializing a Bar object as a Foo. You have two choices here, either initialize it as a straight Bar object or add a getter to the Bar object that connects directly to that property.

Bar bar = new Bar();
bar.a;

or

public class Bar extends Foo{
    public int a = 8;

    public int getA() {
        return a;
    }

    public void addFive(){
        int a += 5;
    }
}

bar.getA();

1 Comment

Why did I get all those down votes for this? At least write something in response.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.