有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何编写适当的OOP代码以避免字段初始化问题?

运行这段代码将打印null

public class Weird {

    static class Collaborator {
        private final String someText;

        public Collaborator(String text) {
            this.someText = text;
        }

        public String asText() {
            return this.someText;
        }
    }

    static class SuperClass {
        Collaborator collaborator;

        public SuperClass() {
            initializeCollaborator();
        }

        protected void initializeCollaborator() {
            this.collaborator = new Collaborator("whatever");
        }

        public String asText() {
            return this.collaborator.asText();
        }
    }

    static class SubClass extends SuperClass {
        String someText = "something";

        @Override
        protected void initializeCollaborator() {
            this.collaborator = new Collaborator(this.someText);
        }
    }

    public static void main(String[] arguments) {
        System.out.println(new Weird.SubClass().asText());
    }
}

(这里也是GitHub Gist

现在,我知道了为什么会发生这种情况(这是因为超类的字段被初始化,然后在子类的字段被初始化之前调用了超类的构造函数

问题是:

  1. 这里的设计问题是什么?从面向对象的角度来看,这种设计有什么问题,以至于结果在程序员看来很奇怪?这种设计突破了什么OOP原则
  2. 如何进行重构,使其不会工作“怪异”,并且是正确的OOP代码

共 (1) 个答案

  1. # 1 楼答案

    这种设计有什么问题:从构造函数调用实例方法,然后在子类中重写它。不要那样做。理想情况下,只能从构造函数体调用私有或最终实例方法,或静态方法。您还将在SuperClass之外公开一个字段(这是一个实现细节),这不是一个好主意——但是编写一个受保护的setCollaborator方法并从initializeCollaborator调用它会产生同样的问题

    至于如何解决这个问题,目前还不清楚你想要实现什么。你为什么需要initializeCollaborator方法呢?解决这个问题的方法多种多样,但它们实际上取决于你是否清楚地知道你想要实现什么。(见鬼,在某些情况下,最好的解决方案是一开始就不使用继承。更喜欢组合而不是继承,等等:)