Is there a way to override class variables in Java?

后端 未结 17 1060
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 09:49
class Dad
{
    protected static String me = \"dad\";

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

class Son extends Dad
{
    protected         


        
相关标签:
17条回答
  • 2020-11-22 10:14

    It indeed prints 'dad', since the field is not overridden but hidden. There are three approaches to make it print 'son':

    Approach 1: override printMe

    class Dad
    {
        protected static String me = "dad";
    
        public void printMe()
        {
            System.out.println(me);
        }
    }
    
    class Son extends Dad
    {
        protected static String me = "son";
    
        @override
        public void printMe()
        {
            System.out.println(me);
        }
    }
    
    public void doIt()
    {
        new Son().printMe();
    }
    

    Approach 2: don't hide the field and initialize it in the constructor

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

    Approach 3: use the static value to initialize a field in the constructor

    class Dad
    {
        private static String meInit = "Dad";
    
        protected String me;
    
        public Dad() 
        {
           me = meInit;
        }
    
        public void printMe()
        {
            System.out.println(me);
        }
    }
    
    class Son extends Dad
    {
        private static String meInit = "son";
    
        public Son()
        {
            me = meInit;
        }
    
    }
    
    public void doIt()
    {
        new Son().printMe();
    }
    
    0 讨论(0)
  • 2020-11-22 10:15

    Though it is true that class variables may only be hidden in subclasses, and not overridden, it is still possible to do what you want without overriding printMe () in subclasses, and reflection is your friend. In the code below I omit exception handling for clarity. Please note that declaring me as protected does not seem to have much sense in this context, as it is going to be hidden in subclasses...

    class Dad
      {
        static String me = "dad";
    
        public void printMe ()
          {
            java.lang.reflect.Field field = this.getClass ().getDeclaredField ("me");
            System.out.println (field.get (null));
          }
      }
    
    0 讨论(0)
  • 2020-11-22 10:15

    only by overriding printMe():

    class Son extends Dad 
    {
        public void printMe() 
        {
            System.out.println("son");
        }
    }
    

    the reference to me in the Dad.printMe method implicitly points to the static field Dad.me, so one way or another you're changing what printMe does in Son...

    0 讨论(0)
  • 2020-11-22 10:16

    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

    0 讨论(0)
  • 2020-11-22 10:16

    https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html

    It's called Hiding Fields

    From the link above

    Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super, which is covered in the next section. Generally speaking, we don't recommend hiding fields as it makes code difficult to read.

    0 讨论(0)
  • 2020-11-22 10:17

    No. Class variables(Also applicable to instance variables) don't exhibit overriding feature in Java as class variables are invoked on the basis of the type of calling object. Added one more class(Human) in the hierarchy to make it more clear. So now we have

    Son extends Dad extends Human

    In the below code, we try to iterate over an array of Human, Dad and Son objects, but it prints Human Class’s values in all cases as the type of calling object was Human.

        class Human
    {
        static String me = "human";
    
        public void printMe()
        {
            System.out.println(me);
        }
    }
    class Dad extends Human
    {
        static String me = "dad";
    
    }
    
    class Son extends Dad
    {
        static String me = "son";
    }
    
    
    public class ClassVariables {
        public static void main(String[] abc)   {
            Human[] humans = new Human[3];
            humans[0] = new Human();
            humans[1] = new Dad();
            humans[2] = new Son();
            for(Human human: humans)   {
                System.out.println(human.me);        // prints human for all objects
            }
        }
    }
    

    Will print

    • human
    • human
    • human

    So no overriding of Class variables.

    If we want to access the class variable of actual object from a reference variable of its parent class, we need to explicitly tell this to compiler by casting parent reference (Human object) to its type.

        System.out.println(((Dad)humans[1]).me);        // prints dad
    
        System.out.println(((Son)humans[2]).me);        // prints son
    

    Will print

    • dad
    • son

    On how part of this question:- As already suggested override the printMe() method in Son class, then on calling

    Son().printMe();
    

    Dad's Class variable "me" will be hidden because the nearest declaration(from Son class printme() method) of the "me"(in Son class) will get the precedence.

    0 讨论(0)
提交回复
热议问题