Рефакторинг некоторого кода с помощью instanceof для перегруженного метода решения в Java - PullRequest
4 голосов
/ 29 июня 2010

У меня есть этот фрагмент кода из GWT в действии:

public void processOperator(final AbstractOperator op) {
        System.out.println("Wordt deze ooit aangeroepen?");
        if (op instanceof BinaryOperator) {
            if ((data.getLastOperator() == null) || (data.isLastOpEquals())) {
                data.setBuffer(Double.parseDouble(data.getDisplay()));
                data.setInitDisplay(true);
            } else {
                data.getLastOperator().operate(data);
            }
            data.setLastOperator(op);
        } else if (op instanceof UnaryOperator) {
            op.operate(data);
        }

        data.setLastOpEquals(false);
}

Я хочу удалить часть 'instanceof' с помощью метода диспетчеризации:

public void processOperator(final BinaryOperator op) {
    if ((data.getLastOperator() == null) || (data.isLastOpEquals())) {
        data.setBuffer(Double.parseDouble(data.getDisplay()));
        data.setInitDisplay(true);
    } else {
        data.getLastOperator().operate(data);
    }
    data.setLastOperator(op); 
    data.setLastOpEquals(false);
}

public void processOperator(final UnaryOperator op) {
    op.operate(data);
    data.setLastOpEquals(false);
}

Но теперь я запускаюв беде в коде ниже из класса ButtonOperator.Следующий код имеет AbstractOperator в качестве типа в конструкторе.Код для типов UnaryOperator и BinaryOperator будет выглядеть точно так же, поэтому он чувствует себя немного громоздким, чтобы создавать специальные конструкторы для них, содержащие точно такой же код.Какой подход лучше?

public ButtonOperator(final CalculatorController controller,
        final AbstractOperator op) {
        super(op.label);

        this.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                controller.processOperator(op);
            }

        });
        this.setStyleName(CalculatorConstants.STYLE_BUTTON);
    }

Ответы [ 2 ]

6 голосов
/ 29 июня 2010

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

UnaryOperator uop = new UnaryOperator(...);
AbstractOperator aop = uop;

...

// This will call the "unary" version of the method
processOperator(uop);

// This will call the "abstract" version of the method
processOperator(aop);

Вы получаете диспетчеризацию вызовов во время выполнения только тогда, когда методы переопределены.

3 голосов
/ 29 июня 2010

Стефан С. объяснил причину.

Чтобы решить эту проблему, вы можете либо переместить метод processOperator() в класс AbstractOperator, чтобы конкретные классы реализовали его:

op.processOperator(controller);

Или используйте шаблон посетителя :

op.processOperator(this); // this = controller.
...