5

Generally Overriding is the concept of Re-defining the meaning of the member in the sub class.Why variables are not behaving like methods while Overriding in java ?
For instance:

class Base {

    int a = 10;

    void display() {
        System.out.println("Inside Base :");
    }
}

class Derived extends Base {

    int a = 99;

    @Override
    // method overriding
    void display() {
        System.out.println("Inside Derived :");
    }
}

public class NewClass {

    public static void main(String... a) {
        Derived d = new Derived();
        Base b = d;
        b.display(); // Dynamic method dispatch
        System.out.println("a=" + b.a);
    }
}

Since data member a is package access specified, it is also available to the Derived class. But generally while calling the overridden method using the base class reference, the method that is redefined in derived class is called (Dynamic method dispatch)..but it is not the same for the variable..why.?

EXPECTED OUTPUT

Inside Derived :
a=99

OBTAINED OUTPUT:

Inside Derived :
a=10

Prints 10 - why the variable does not behave similar to method in the derived class?
Why the variables are not allowed to be overridden in the sub class?

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
mavis
  • 3,100
  • 3
  • 24
  • 32
  • 9
    ...Because that's how Java was designed? – Louis Wasserman Jun 19 '13 at 21:00
  • See this related SO question: http://stackoverflow.com/questions/685300/is-there-a-way-to-override-class-variables-in-java – paulrehkugler Jun 19 '13 at 21:01
  • I think it's great to understand how this works, but your example is exactly why you shouldn't mix package-private members with inheritance. The fact that your code will act differently if you move one of the classes to a different package violates the principle of least surprise, and it makes for non-transparent code. – Mark Peters Jun 19 '13 at 21:04
  • You can't override fields, only hide them. – Peter Lawrey Jun 19 '13 at 21:07

10 Answers10

7

You typed b as an instance of Base. So when the compiler needs to resolve b.a, it looks to the definition of Base for the meaning of b.a. There is no polymorphism for instance fields.

jason
  • 236,483
  • 35
  • 423
  • 525
2

Because the only thing that polymorphism ever applies to in Java is instance method.

Hence, you can neither override static members, nor the instance member fields. By, having these members in a derived class with the same names you're simply hiding them with a new definition.

System.out.println("a="+b.a);

Although, Base b may point to a sub-class object (at runtime) the a above has already been bound to Base class at compile time (static binding). Hence, it prints 10.

Ravi K Thapliyal
  • 51,095
  • 9
  • 76
  • 89
2

Variables behave like that because they lack behavior. In other words, variables are passive.

There is nothing about a variable's definition that a derived class can reasonably change by overriding:

  • It cannot change its type, because doing so may break methods of the base class;
  • It cannot reduce its visibility, because that would break the substitution principle.
  • It cannot make it final without making it useless to the base class.

Therefore, member variables declared in derived classes hide variables from the base class.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • "There is nothing about a variable that a derived class can reasonably change by overriding" - oh yes there is - the value - `Base{String name; print(){sysout(name);}} Derived{String name="derived";}` - would have many uses – Mr_and_Mrs_D Jul 20 '13 at 19:43
  • @Mr_and_Mrs_D Ah, I didn't mean the value, only the definition. This is now corrected. – Sergey Kalinichenko Jul 20 '13 at 20:16
1

There is no way to override a class variable. You do not override class variables in Java you hide them. Overriding is for instance methods.

Zzz
  • 2,927
  • 5
  • 36
  • 58
1

In this case, it might be a good idea to write a getter method:

public int getA(){
  return 99;
}

Now you can override it in a derived class.

Lucky
  • 4,787
  • 9
  • 40
  • 50
1

First, we don't override any class variable. Methods only.

Second, if you would like to see that the variable value has been updated or replaced, you should rather declare it as "static int" instead of "int". In this way, it will work as everybody is sharing the same variable, and the new value will be put on it.

Third, if you would like to see that the variable value being assigned and used differently, you could design it as passing a parameter in constructor, or something similar, to make it work accordingly as you desire.

0

The answer to this has to do with variable scoping, not polymorphism. In other words, you're overriding that variable in the class scope. So, d.a will return the variable in Derived's class scope, but b.a will return the variable in Base's class scope.

paulrehkugler
  • 3,241
  • 24
  • 45
0

In OOP (Object Oriented Programming) the idea is to hide the data in the object and let object only communicate with invoking methods. That's why variables cannot be overloaded, in fact they are "scoped"/"attached" to a specific class.

Also the derived class should not define a again, it is already defined in the base class, so simply set a on the object to the desired value, e.g:

class Base {
    private int a = 10;
    public int getA() { return a; }
    public void setA(inta) { this.a = a; }
}

class Derived extends Base {
    // adding new variables, override methods, ...
}

// then later:

Derived d = new Derived();
d.setA(99); // override the default value 10
clearwater
  • 514
  • 2
  • 7
  • For reference, making a variable private and then providing a public getter and setter for it, is hardly "hiding" the data. :P – cHao Jul 20 '13 at 20:20
  • You will notice that there is no access to the real data member in the (very simple) example. The version above is hiding all the knowledge about the information how the value is stored and providing an API how to access it. See the following link for more information on the "information hiding" in general: http://en.wikipedia.org/wiki/Information_hiding – clearwater Jul 22 '13 at 10:58
  • Wikipedia doesn't disagree with me here. The only thing that's happened here, is that there's no knowledge that `a` is *just* a variable. But that's exactly what the code will be treating it as, and if you made it be anything more complex than that, added restrictions on the possible values, etc., you could very well break any assumptions made by the code that uses this interface. So the design decisions are already leaked, and nothing's really "hidden" here. – cHao Jul 22 '13 at 13:22
  • And of course, everything you've demonstrated so far can be done with a public variable. So this basically looks to this point like indirection for the sake of indirection, or "because my teacher said make all variables private". – cHao Jul 22 '13 at 13:28
  • It's hardly about "because my teacher said" but about avoiding practical issues later in time when the software starts to change or suddenly getA() for a specific subclass needs to be working slightly differently. With practical I mean in real life software needs to perform a task and maintenance costs need to be minimal; also backward compatibility is often very critical. So as long as one hides the data (field) as above certain issues are not appearing since all the classes do is to implement the promised contract but not to expose how the data is stored. – clearwater Jul 22 '13 at 16:07
  • Then your answer could use some demonstration of the value of a getter/setter. As they stand, `getA()` and `setA()` provide no obvious value over or above that of a public variable, and you've already demonstrated them breaking encapsulation via `d.setA(99);`. (The setting should have been done in the derived class during construction, but was done -- *easily* -- outside of it). You don't get to bring up good OOP practices, and then ignore encapsulation -- which is arguably the single most important, and apparently least understood, OO concept. – cHao Jul 22 '13 at 18:53
  • Okay I recognize your effort: Can you provide some links to some books or articles why using setters the way I did is bad in OO and what would be better OOP practices? It'll need more text than it fits into these comments to understand that. – clearwater Aug 05 '13 at 18:18
  • http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html and http://typicalprogrammer.com/?p=23 would be a good start. Also see http://stackoverflow.com/a/565117/319403 and http://java.dzone.com/articles/getter-setter-use-or-not-use-0 . – cHao Aug 05 '13 at 18:29
  • As for better practices... Outside of a Java bean, most uses of get/set properties totally miss the point of encapsulation. If i have to `setA(stuff)` before i `doWork()`, that's an implementation detail. You know...the very thing encapsulation is supposed to be hiding from us. There's no good reason for it; the constructor simply isn't doing its job. `stuff` almost always should have been an argument to the constructor (which would set it appropriately), or to `doWork`...or to a factory method that has access to that info, if you don't. – cHao Aug 05 '13 at 19:12
0

What would happen if variables could override other variables? Suddenly your class has to be aware of what variables the parent class is using, lest you accidentally override one and break whatever was using it in the parent class. The whole point of encapsulation is to avoid having that kind of intimate knowledge of another object's internal state. So instead, variables shadow same-named other variables, and which one you see depends on what type you're trying to reach the variable through.

There's hope, though. If all you want is to override the value, you don't have to redeclare the variable. Just change the value in an init block. If the base class is harmed by you doing that, then it chose the wrong visibility for that variable.

class Base {
    int a = 10;
}

class Derived extends Base {
    { a = 99; }
}

Of course, this doesn't work very well for final variables.

cHao
  • 84,970
  • 20
  • 145
  • 172
0
  1. we don't override any class variable. Methods only.
  2. If you would like to see that the variable value has been updated or replaced, you should rather declare it as "static int" instead of "int". In this way, it will work as everybody is sharing the same variable, and the new value will be put on it.
  3. If you would like to see that the variable value being assigned and used differently, you could design it as passing a parameter in constructor, or something similar, to make it work accordingly as you desire.

Moreover, if variables are overridden then what is left with a parent class of its own,it breaches the class security if java would give the access to change the value of variable of parent class.

Tushar Gupta - curioustushar
  • 58,085
  • 24
  • 103
  • 107
Aasif Ali
  • 11
  • 3
  • 1. That's been established; the question was *why* it's that way. – cHao Aug 05 '13 at 15:46
  • 2. The point might not be to share values across all instances. It might be, for example, to have an int describing the type of object within the family. (Reflection would be better for this, but isn't foolproof -- and effectively requires foreknowledge of the different types in order to be useful.) – cHao Aug 05 '13 at 15:47
  • As for that last sentence, it may need a rewrite. I find it impossible to be sure what it's saying. But for reference, `private` and `protected` aren't about security; there are ways around them via reflection, rigged JVMs, etc. What they're for is to guide users of the class into using it as intended, by requiring extra effort if they want to do the wrong thing. – cHao Aug 05 '13 at 15:50