简体   繁体   English

非重写方法不显示子类字段

[英]Non overridden method doesn't show subclass field

class Parent {
    String st = "external";

    void print() {
        System.out.println(st); 
        System.out.println(this.st);
    }
}

class Child extends Parent {
    String st = "inner";
}

public static void main(String[] args) {
    new Child().print(); // shows "external"
}

Why does print() called on subclass not show the string "inner"? 为什么在子类上调用的print()不显示字符串“inner”?

why print() called on subclass doesn't show string - "inner" ? 为什么print()调用子类不显示字符串 - “内部”?

Because member variables cannot be overridden. 因为成员变量无法被覆盖。 The member variable st in class Child does not override the member variable st in class Parent . 成员变量stChild不会覆盖成员变量stParent The two member variables are two separate variables, which happen to have the same name. 两个成员变量是两个独立的变量,它们碰巧具有相同的名称。

The methods in class Parent see the member variable st that is defined in class Parent , and not the one in class Child , even if the object is really an instance of class Child . 在类中的方法Parent看到成员变量st是在类中定义的Parent ,而不是一个在课堂上Child ,即使对象是真正的类的实例Child

Only methods can be overridden. 只能覆盖方法。

More information in Oracle's Java Tutorials: Hiding Fields (thanks @JonK). Oracle Java教程中的更多信息: 隐藏字段 (感谢@JonK)。

As the others mentioned the field st of the Parent class is hidden. 正如其他人提到的那样,隐藏了Parent类的字段st Just an addition if you want it to print "inner". 如果你想要它打印“内部”,只是一个补充。

Change Child class to this: Child类更改为:

class Child extends Parent {
    public Child() {
        st = "inner";
    }
}

This way the value of st from the Parent class is overriden! 这样,来自Parent类的st的值被覆盖!

why print() called on subclass doesn't show string - "inner" ? 为什么print()调用子类不显示字符串 - “内部”?

why should it? 为什么要这样? you are calling the method print() that is only override in the parent class up there in the parent class st is only holding the value " external " 你正在调用方法print() ,它只是在父类中覆盖,在父类中,st只保存值“ external

The other answers cover why the behavior you notice is expected, so I won't touch on that. 其他答案涵盖了您注意到的行为的原因,因此我不会涉及到这一点。 In terms of a solution to your problem, there are a few worth mention (neglecting things like reflection and subclass casting; technically solutions, but poor ones). 就你的问题的解决方案而言,有一些值得一提(忽略了诸如反射和子类投射之类的东西;技术上的解决方案,但是糟糕的解决方案)。

Option 1: Set Parameter 选项1:设置参数

As Will mentioned, can simply set the parameter in Child: 如上所述,可以简单地在Child中设置参数:

class Child extends Parent{
    public Child() {
        st = "inner";
    }
}

Option 2: Method Override 选项2:方法覆盖

Can also override the print() method (because, as mentioned, only methods can be overridden). 也可以覆盖print()方法(因为,如上所述,只能覆盖方法)。 Child would become something along the lines of: Child会成为:

class Child extends Parent{
    ...

    @Override
    void print() {
        // Child-specific implementation here.
    }
}

This will result in Child objects using their print method in place of Parent 's method. 这将导致Child对象使用其print方法代替Parent的方法。

Option 3: Strategy Pattern 备选方案3:战略模式

Another option is to use Strategy pattern. 另一种选择是使用策略模式。 Consider the following: 考虑以下:

public interface Strategy {
    String getString();
}

public class ParentStrategy implements Strategy {
    @Override
    public String getString() {
        return "external";
    }
}

public class ChildStrategy implements Strategy {
    @Override
    public String getString() {
        return "inner";
    }   
}

From here, all you need to do is change your Parent object so that it defaults to ParentStrategy, provide accessors to change the Strategy, change its print method to use the getString() method of its Strategy object, and change the Strategy in Child to use ChildStrategy: 从这里,您需要做的就是更改您的Parent对象,使其默认为ParentStrategy,提供更改策略的访问者,更改其print方法以使用其Strategy对象的getString()方法,并将Child中的策略更改为使用ChildStrategy:

class Parent{
    Strategy strat = new ParentStrategy();

    void setStrategy(Strategy s) {
        strat = s;
    }

    void print() {
        System.out.println(strat.getString()); 
    }
}
class Child extends Parent{
    public Child() {
        super();
        setStrategy(new ChildStrategy());
    }
}

In real world applications, this pattern is a fundamental tool to making flexible applications. 在实际应用中,这种模式是制作灵活应用程序的基本工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM