Не вызывайте методы подкласса из конструктора суперкласса - PullRequest
3 голосов
/ 18 июня 2010

Рассмотрим следующий код

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package example0;

/**
 *
 * @author yccheok
 */
public class Main {

    static class A {
        private final String var;

        public A() {
            var = getVar();
            // Null Pointer Exception.
            System.out.println("var string length is " + var.length());
        }

        public String getVar() {
            return "String from A";
        }
    }

    static class B extends A {
        private final String bString;

        // Before B ever constructed, A constructor will be called.
        // A is invoking a overriden getVar, which is trying to return
        // an initialized bString.
        public B() {                
            bString = "String from B";
        }

        @Override
        public String getVar() {
            return bString;
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        B b = new B();
    }

}

В настоящее время, на мой взгляд, есть два способа избежать такой проблемы.

Либо делаю урок А финальный класс.

static final class A {
    private final String var;

    public A() {
        var = getVar();
        // Null Pointer Exception.
        System.out.println("var string length is " + var.length());
    }

    public String getVar() {
        return "String from A";
    }
}

Или

Завершение метода getVar

static class A {
    private final String var;

    public A() {
        var = getVar();
        // Null Pointer Exception.
        System.out.println("var string length is " + var.length());
    }

    public final String getVar() {
        return "String from A";
    }
}

Автор пытается предложить способы предотвращения вышеуказанной проблемы. Однако решение кажется обременительным, поскольку есть некоторые правила, которым нужно следовать.

http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/

Помимо окончательного выполнения и предложенного автором способа, есть ли еще способы предотвратить возникновение вышеуказанной проблемы (не вызывать методы подкласса из конструктора суперкласса)?

1 Ответ

2 голосов
/ 18 июня 2010

Завершение метода getVar

Это определенно то, что вам нужно сделать.

Если вы используете функциональность метода для инициализации объекта, вы не должны позволять подклассам нарушать этот метод.

Отвечая на ваш вопрос, другой способ предотвратить это - сделать getVar приватным в A.

См. Эту упрощенную версию вашего кода:

// A.java
class A {
    private final String var;
    public A(){
        var = getVar();
        var.length();
    }
    private String getVar(){
        return "This is the value";
    }
}
class B extends A {
    private final String other;
    public B(){
        other = "Other string";
    }
    public String getVar(){
        return other;
    }
}
class Main{
    public static void main( String [] args ) {
        new B();
    }
}

Кстати, почему вы поместили их как статические вложенные классы, просто чтобы создать путаницу?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...