Is there a way to override class variables in Java?

219,377

Solution 1

Yes. But as the variable is concerned it is overwrite (Giving new value to variable. Giving new definition to the function is Override). Just don't declare the variable but initialize (change) in the constructor or static block.

The value will get reflected when using in the blocks of parent class

if the variable is static then change the value during initialization itself with static block,

class Son extends Dad {
    static { 
       me = "son"; 
    }
}

or else change in constructor.

You can also change the value later in any blocks. It will get reflected in super class

Solution 2

In short, no, 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. Hiding is different from overriding.

In the example you've given, by declaring the class variable with the name 'me' in class Son you hide the class variable it would have inherited from its superclass Dad with the same name 'me'. Hiding a variable in this way does not affect the value of the class variable 'me' in the superclass Dad.

For the second part of your question, of how to make it print "son", I'd set the value via the constructor. Although the code below departs from your original question quite a lot, I would write it something like this;

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void printName() {
        System.out.println(name);
    }
}

The JLS gives a lot more detail on hiding in section 8.3 - Field Declarations

Solution 3

Yes, just override the printMe() method:

class Son extends Dad {
        public static final String me = "son";

        @Override
        public void printMe() {
                System.out.println(me);
        }
}

Solution 4

You can create a getter and then override that getter. It's particularly useful if the variable you are overriding is a sub-class of itself. Imagine your super class has an Object member but in your sub-class this is now more defined to be an Integer.

class Dad
{
        private static final String me = "dad";

        protected String getMe() {
            return me;
        }

        public void printMe()
        {
                System.out.println(getMe());
        }
}

class Son extends Dad
{
        private static final String me = "son";

        @Override
        protected String getMe() {
            return me;
        }
}

public void doIt()
{
        new Son().printMe(); //Prints "son"
}

Solution 5

If you are going to override it I don't see a valid reason to keep this static. I would suggest the use of abstraction (see example code). :

     public interface Person {
        public abstract String getName();
       //this will be different for each person, so no need to make it concrete
        public abstract void setName(String name);
    }

Now we can add the Dad:

public class Dad implements Person {

    private String name;

    public Dad(String name) {
        setName(name);
    }

    @Override
    public final String getName() {
    return name;
    }

    @Override
    public final void setName(String name) {
        this.name = name;
    }
}

the son:

public class Son implements Person {

    private String name;

    public Son(String name) {
        setName(name);
    }

    @Override
    public final String getName() {
        return name;
    }

    @Override
    public final void setName(String name) {
        this.name = name;
    }
}

and Dad met a nice lady:

public class StepMom implements Person {

    private String name;

    public StepMom(String name) {
        setName(name);
    }

    @Override
    public final String getName() {
        return name;
    }

    @Override
    public final void setName(String name) {
        this.name = name;
    }
}

Looks like we have a family, lets tell the world their names:

public class ConsoleGUI {

    public static void main(String[] args) {
        List<Person> family = new ArrayList<Person>();
        family.add(new Son("Tommy"));
        family.add(new StepMom("Nancy"));
        family.add(new Dad("Dad"));
        for (Person person : family) {
            //using the getName vs printName lets the caller, in this case the
            //ConsoleGUI determine versus being forced to output through the console. 
            System.out.print(person.getName() + " ");
            System.err.print(person.getName() + " ");
            JOptionPane.showMessageDialog(null, person.getName());
    }
}

}

System.out Output : Tommy Nancy Dad
System.err is the same as above(just has red font)
JOption Output:
Tommy then
Nancy then
Dad

Share:
219,377

Related videos on Youtube

Dikla
Author by

Dikla

Updated on January 16, 2021

Comments

  • Dikla
    Dikla over 3 years
    class Dad
    {
        protected static String me = "dad";
    
        public void printMe()
        {
            System.out.println(me);
        }
    }
    
    class Son extends Dad
    {
        protected static String me = "son";
    }
    
    public void doIt()
    {
        new Son().printMe();
    }
    

    The function doIt will print "dad". Is there a way to make it print "son"?

    • Brett
      Brett about 15 years
      If you ever see a protected static, run.
    • Tony Chan
      Tony Chan about 11 years
      @TomHawtin-tackline forgive my ignorance, but why is a protected static frowned upon? I tried googling but can't find a clear answer. Thanks
    • Zeeshan
      Zeeshan almost 10 years
  • Chii
    Chii about 15 years
    whats incorrect about this? If the 'me' member variable is supposed to be overridable in your design, then patrick's is the correct solution
  • Brett
    Brett about 15 years
    You can't override any statics.
  • Brett
    Brett about 15 years
    (or at least it doesn't make sense, IFSWIM.)
  • Nate Parsons
    Nate Parsons about 15 years
    Actually, if the value of me is the same for every instance, just removing 'static' would be fine. Initialization doesn't have to be in constructor.
  • Patrick Cornelissen
    Patrick Cornelissen about 15 years
    Right, although technically (in bytecode) I think it's almost the same ;-)
  • AutomatedMike
    AutomatedMike over 11 years
    In this case you are "hiding" the variable from the super class. This is distinct from overriding and has nothing to do with inheritance. Other classes will see one variable or the other depending on whether they referenced the base-class or the sub-class and the one they see is fixed at compile time. If you changed the name "me" in the sub class to something else you would get the same effect. Most IDEs and code validation tools (findbugs etc) will warn you when you hide variables like this since it is usually not what you want to do.
  • siddagrl
    siddagrl over 10 years
    Override is possible by having a static block in the derived class
  • Corley Brigman
    Corley Brigman over 10 years
    isn't this the same as the original question?
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 10 years
    @siddagrl: can you elaborate ?
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 10 years
    CAn you explain why ? (in your answer)
  • n611x007
    n611x007 about 10 years
    which of OP's classes is Person supposed to replace in this example?
  • nckbrz
    nckbrz about 10 years
    You are looking at programming from the perspective of coding alone. Which is fine, code however you want in that case. If you look at coding from the view of a team member, then the rules become clear, such as to why fields aren't overridable and so on. I could give you a speech as to why, but if you aren't seeing it from that perspective of a team member, you will just see my points as invalid and throw invalid arguments back at me.
  • nckbrz
    nckbrz about 10 years
    Very interesting, Java.lang.reflect huh?... +1
  • RichieHH
    RichieHH about 10 years
    The OP was regarding changing access to statics. Hence the "me" was a generic "dad" or "son" - something that doesnt need creating for every dad or son and hence is a static.
  • nckbrz
    nckbrz about 10 years
    Yeah, your right, I didn't see that it was static. Haha, that would change my answer to about 100 less lines of code,l if answered at all. Thanks for the heads up
  • Panzercrisis
    Panzercrisis almost 10 years
    @naxa Son and Dad are supposed to inherit from Person, then call super("Son or Dad"); in their constructors.
  • Panzercrisis
    Panzercrisis almost 10 years
    Is it considered good or bad to hide variables like that in Java?
  • Cléssio Mendes
    Cléssio Mendes about 9 years
    I think the answer should have some code for better readability. Just change the Son implementation to class Son extends Dad { static { me = 'son' } }
  • Sudheer Aedama
    Sudheer Aedama almost 9 years
    what if the library that you are using does not have printMe() method, or even it has that method it's a static method ?
  • Ring
    Ring over 7 years
    To make this a more real life example, you could consider that the "printMe" method could be a very complicated function with logic you don't want to repeat. In this example, you just want to change the name of the person, not the logic that prints it. You should create a method called "getName" which you would override to return "son" and the printMe method would invoke the getName method as part of its printing.
  • Dale
    Dale over 7 years
    Correct, you can't override statics. You can SHADOW them or some people called me MASKING.
  • FelixSFD
    FelixSFD over 7 years
    A link to a potential solution is always welcome, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. Take into account that being barely more than a link to an external site is a possible reason as to Why and how are some answers deleted?.
  • Rik Schaaf
    Rik Schaaf over 2 years
    This will actually change the value of me in the Dad class, which I don't think is something that is preferred.
  • Rik Schaaf
    Rik Schaaf over 2 years
    Be careful though, if you declare the me variable protected, you'd also have to enable access to the variable, before you can use it, because Dad has no access to Son's protected fields.