Java - ООП - применять конкретную реализацию во время компиляции - PullRequest
0 голосов
/ 11 июня 2018

В моем коде есть набор «фабрик» (IfaceProducerProcessor), создающих разные внутренние реализации одного и того же интерфейса (Iface).Эти фабрики также должны иметь возможность впоследствии выполнять некоторую обработку для экземпляра, который они произвели, но не для других реализаций Iface.

Излишне говорить, что вызывающий код не должен знать подробности реализации или внутреннийинтерфейсы конкретного Iface экземпляра, только для того, чтобы он передавал его только своему первоначальному производителю для обработки.

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

interface Iface {
    void foo();
}

interface IfaceProducerProcessor {
    Iface produceIface();
    void processIface(Iface iface);
}

class A implements IfaceProducerProcessor {
    Iface produceIface() {
        return new AIfaceImpl();
    }

    void processIface(Iface iface) {
        // How to enforce AIfaceImpl in compile-time?
        if (!(iface instanceof AIfaceImpl)) {
            throw IlleagalArgumentException("Expected instanceof AIfaceImpl.");
        }

        ...

        ((AIfaceImpl)iface).bar();

        ...
    }

    class AIfaceImpl implements Iface {
        // implementation of foo() ...

        void bar() {

        }
    }
}

class B implements IfaceProducerProcessor {

    ...

    class BIfaceImpl implements Iface {

        ...

    }
}

...

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

1 Ответ

0 голосов
/ 11 июня 2018

Ваше предположение о дженериках может работать лучше, рассмотрите следующие изменения на IfaceProducerProcessor.Обратите внимание на общий параметр I, который является реализацией только Iface:

interface IfaceProducerProcessor<I extends Iface> {
    I produceIface();
    void processIface(I iface);
}

, который затем реализует класс A со следующим определением:

class A implements IfaceProducerProcessor<AIfaceImpl>{
     public AIfaceImpl produceIface(){
         /* ... */
     }

     public void processIface(AIfaceImpl iface){
         /* ... */
     }
}

Таким образом, через компилятор вы принудительно используете AIfaceImpl в этом конкретном IfaceProducerProcessor.

То же самое можно сделать для каждой реализации IfaceProducerProcessor:

class B implements IfaceProducerProcessor<BIfaceImpl>{
    /* ... */
}

и т. Д.

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