Как заставить подкласс вызывать абстрактный реализованный метод - PullRequest
6 голосов
/ 20 июля 2011

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

Я написал это один раз в конструкторе суперкласса, потому что я хочу, чтобы он вызывал его для каждой реализации.

public abstract class SupahClass {
    public SupahClass() {
        doStuff(); // It IS executed when the subclass constructor is called
        init(); // NOT executed, even though it's implemented
    }

    private void doStuff() { ... }        

    protected abstract void init();
}

public class SomeSubClass extends SupahClass {

    // The problem lies HERE: this is executed AFTER init() ... so it gets NULL again
    private TextBox myTextBox = null;

    public SomeSubClass() {
        super(); // invokes the super constructor, so init() should be called
        // I could call init(); here EACH time i create a new subclass... but no :)
    }

    @Override
    public void init() {
        this.myTextBox = new TextBox(); // Executed BEFORE its declared as null above
    }
}

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

EDIT См. Свойство подкласса myTextBox и реализацию init()

Как вы думаете, какой подход я должен сделать? Удалите = null в декларации свойства (duhhh)

или удалите init() в суперклассе и явно вызовите его в конструкторе подкласса (это то, чего я хотел избежать, поскольку мне придется писать его 100% времени ..)

Ответы [ 4 ]

8 голосов
/ 20 июля 2011

Я не могу воспроизвести это.Будет вызван init() , при условии, что сначала не будет выдано никаких исключений.Короткий, но завершенный пример:

abstract class Superclass {
   public Superclass() {
       init();
   }

   protected abstract void init();
}

class Subclass extends Superclass {
   public Subclass() {
       super();
   }

   @Override
   public void init() {
       System.out.println("Subclass.init called");
   }
}

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

Это печатает «Subclass.init said», как и ожидалось.Я подозреваю, что что-то не так в коде, который вы нам не показали.

Обратите внимание, что вызов виртуальных методов в конструкторе - рискованное дело - подкласс еще не был инициализирован - все переменные будут иметьих значения по умолчанию, например.Как правило, этого следует избегать.

2 голосов
/ 20 июля 2011

Вы можете исправить это, изменив декларацию на:

private TextBox myTextBox;

Присвоение null не имеет смысла. Если бы не было суперкласса, он бы ничего не делал, потому что поля в любом случае инициализируются нулем. Так как есть суперкласс, он действует как выстрел в ногу. Так что избавься от этого.

2 голосов
/ 20 июля 2011

Абстрактные классы могут вызывать абстрактные методы.

0 голосов
/ 23 сентября 2011

Использовали ли вы отладчик, чтобы понять, что делает код?

Порядок строительства 1. конструктор базового класса 2. инициализировать все члены производного класса 3. конструктор производного класса.

В вашем случае шаг 1 инициализирует член (в инициализации производного класса - вызывается с помощью полиморфного вызова), но шаг 2 устанавливает его в ноль.

...