有没有办法覆盖 Java 中的类变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/685300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:54:12  来源:igfitidea点击:

Is there a way to override class variables in Java?

javainheritanceoverriding

提问by Dikla

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"?

函数 doIt 将打印“爸爸”。有没有办法让它打印“儿子”?

采纳答案by Vivek MVK

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.

是的。但是就变量而言,它被覆盖(为变量赋予新值。为函数赋予新定义是覆盖)。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

您也可以稍后在任何块中更改该值。它将反映在超类中

回答by Romain Linsolas

Yes, just override the printMe()method:

是的,只需覆盖该printMe()方法:

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

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

回答by Dan Vinton

only by overriding printMe():

只能通过覆盖printMe()

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

the reference to mein the Dad.printMemethod implicitly points to the static field Dad.me, so one way or another you're changing what printMedoes in Son...

引用meDad.printMe方法隐含指向静态字段Dad.me,所以拉上你改变什么printMe的呢Son

回答by Patrick Cornelissen

This looks like a design flaw.

这看起来像是一个设计缺陷。

Remove the static keyword and set the variable for example in the constructor. This way Son just sets the variable to a different value in his constructor.

删除 static 关键字并设置变量,例如在构造函数中。这样 Son 只需在他的构造函数中将变量设置为不同的值。

回答by Ionel Bratianu

You cannot override variables in a class. You can override only methods. You should keep the variables private otherwise you can get a lot of problems.

您不能覆盖类中的变量。您只能覆盖方法。你应该保持变量私有,否则你会遇到很多问题。

回答by Mike

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.

您不会在 Java 中覆盖您隐藏它们的类变量。覆盖是例如方法。隐藏与覆盖不同。

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.

在您给出的示例中,通过在类 Son 中声明名为 'me' 的类变量,您隐藏了它将从其父类继承的具有相同名称 'me' 的类变量。以这种方式隐藏变量不会影响超类Dad中类变量'me'的值。

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

JLS 在第8.3- 字段声明中提供了更多有关隐藏的详细信息

回答by John Strickler

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 Objectmember but in your sub-class this is now more defined to be an Integer.

您可以创建一个 getter,然后覆盖该 getter。如果您要覆盖的变量是其自身的子类,则它特别有用。想象一下你的超类有一个Object成员,但在你的子类中,它现在更定义为一个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"
}

回答by Pixel

Of course using private attributes, and getters and setters would be the recommended thing to do, but I tested the following, and it works... See the comment in the code

当然,使用私有属性,getter 和 setter 将是推荐的做法,但我测试了以下内容,并且它有效......请参阅代码中的注释

class Dad
{
    protected static String me = "dad";

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

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

    /* 
    Adding Method printMe() to this class, outputs son 
    even though Attribute me from class Dad can apparently not be overridden
    */

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

class Tester
{
    public static void main(String[] arg)
    {
        new Son().printMe();
    }
}

Sooo ... did I just redefine the rules of inheritance or did I put Oracle into a tricky situation ? To me, protected static String me is clearly overridden, as you can see when you execute this program. Also, it does not make any sense to me why attributes should not be overridable.

Sooo ...我只是重新定义了继承规则还是我让 Oracle 陷入了一个棘手的境地?对我来说,protected static String me 显然被覆盖了,正如您在执行此程序时所看到的。此外,为什么属性不应该被覆盖对我来说没有任何意义。

回答by Sergey Ushakov

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 meas protecteddoes not seem to have much sense in this context, as it is going to be hidden in subclasses...

虽然类变量确实可能只隐藏在子类中,而不是被覆盖,但仍然可以做你想做的事而不覆盖printMe ()子类,反射是你的朋友。在下面的代码中,为了清楚起见,我省略了异常处理。请注意,在这种情况下声明measprotected似乎没有多大意义,因为它将隐藏在子类中......

class Dad
  {
    static String me = "dad";

    public void printMe ()
      {
        java.lang.reflect.Field field = this.getClass ().getDeclaredField ("me");
        System.out.println (field.get (null));
      }
  }

回答by user2895864

class Dad
{
    protected static String me = "dad";

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

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

public void doIt()
{
    new Son().printMe();
}

... will print "son".

...将打印“儿子”。

回答by nckbrz

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

System.out 输出:Tommy Nancy Dad
System.err 和上面一样(只是有红色字体)
JOption 输出:
Tommy then
Nancy then
Dad