在抽象方法中访问实例变量的陷阱

在Java设计模式中,模板方法是很常用的一种模式,它的宗旨就是把子类相同的部分提取到父类,不同的部分通过声明抽象方法在父类中调用,在子类中实现。

但是如果在抽象方法中访问实例变量,可能会有一个让你意外的陷阱:

 

public class Test {
    public static void main(String[] args) {
        new ChildClass();
    }
}

abstract class SuperClass {
    private int i = 0;

    SuperClass() {
        foo();
    }

    abstract void foo();
}

class ChildClass extends SuperClass {
    private int i = 5;

    void foo() {
        System.out.println("i = " + i);
    }
}

 

父类中的foo()方法调用的确实是子类中实现的foo方法。

 

在子类中,我们期望变量i象我们初始化的那样,值为5,但是实际上它的值不是子类中赋予的5,而是父类中赋予的0。

实际上子类的初始化过程如下:

 

1)初始化父类的实例变量

2)调用父类的构造器

3)调用子类的foo()方法

4)初始化子类的实例变量

5)调用子类的构造器

 

因此,如果我们在父类的构造器中调用抽象函数,而该函数又要访问实例变量的值的时候,就要特别注意到这种情况。

你可能感兴趣的:(设计模式)