根据子类型信息初始化超类成员

时间:2012-02-13 17:32:20

标签: java constructor subclass

我有以下情况:

        public abstract class A {
            private Object superMember;
            public A() {
                superMember = initializeSuperMember();
                // some additional checks and stuff based on the initialization of superMember (***)
            }

            protected abstract Object initializeSuperMember();
        }

        class B extends A {
            private Object subMember;
            public B(Object subMember) {
                super();
                subMember = subMember;
            }

            protected Object initializeSuperMember() {
                // doesn't matter what method is called on subMember, just that there is an access on it
                return subMember.get(); // => NPE
            }
        }

问题是我在创建新对象B时获得了NPE 我知道我可以通过在子类构造函数中分配subMember内容后调用initializeSuperMember()来避免这种情况,但这意味着我必须为每个子类执行此操作(在代码中标记为 * ) 。
因为我必须在子类构造函数中调用super()作为第一件事,所以在调用super()之前我无法初始化subMember。

任何人都想告诉我,如果有更好的方法可以做到这一点,或者我是否想要做一些完全错误的事情?

4 个答案:

答案 0 :(得分:2)

两个问题:

首先,您应该永远不要从构造函数中调用可重写的成员函数,因为您发现的原因。有关该问题的详细讨论,请参阅this thread

其次,在B的构造函数中,您需要:

this.subMember = subMember;

构造函数参数名称掩盖了字段名称,因此您需要this.来引用该字段。

答案 1 :(得分:0)

遵循调用链:

  1. 您调用B()构造函数。
  2. 它调用A()构造函数。
  3. A()构造函数调用重写的抽象methot
  4. 方法B#initializeSuperMember()引用尚未初始化的subMember。 NPE。
  5. 做你做的事永远无效。

    此外,目前还不清楚你想要完成什么。你应该问一个单独的问题来解释你的目标是什么。

答案 2 :(得分:0)

问题是当你调用super()时,subMember尚未初始化。您需要将subMemeber作为参数传递。

public abstract class A {
    public A (Object subMember) {
        // initialize here
    }
}


class B extends A {
    public B (Object subMember) {
        super(subMember);
        // do your other things
    }
}

由于您不希望在抽象类中使用subMember,因此另一种方法是覆盖getter。

public abstract class A {
    public abstract Object getSuperMember();
    protected void checkSuperMember() {
        // check if the supberMember is fine
    }
}

public class B extends A {
    private Object subMember;
    public B(Object subMember) {
        super();
        this.subMember = subMember;
        checkSuperMemeber();
    }

    @Override
    public Object getSuperMember() {
        return subMember.get();
    }
}

我希望这也可以删除您的重复代码。

答案 3 :(得分:0)

嗯,这段代码看起来不太好,而且很可能这表明情况很糟糕。但是有一些技巧可以帮助你做你想做的事情,使用这样的工厂方法:

public static abstract class A {
    public abstract Object createObject();
}

public static abstract class B extends A {
    private Object member;

    public B(Object member) {
        super();
        this.member = member;
    }

}

public static B createB(final Object member) {
    return new B(member) {

        @Override
        public Object createObject() {
            return member.getClass();
        }
    };
}