Вызов Java неуниверсального метода из универсального метода - PullRequest
0 голосов
/ 04 ноября 2018

Я пытаюсь что-то изменить. У меня есть следующая иерархия классов:

class BaseItem {..}
class ItemA extends BaseItem {..}
class ItemB extends BaseItem {..}
class BaseContext<T extends BaseItem> {..}
class ContextA extends BaseContext<ItemA> {..}
class ContextB extends BaseContext<ItemB> {..}

И 2 метода, которые потребитель должен использовать:

public void methodA(ItemA) {..}
public void methodB(ItemB) {..}

Возможно ли как-то иметь общий Потребитель для этих двух методов? Прямо сейчас у меня есть 2 неуниверсальных:

Consumer<ContextA> consumerA = ctx -> methodA(ctx.getItem());
Consumer<ContextB> consumerB = ctx -> methodB(ctx.getItem());

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

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

2 метода ожидают определенных подтипов Item, а не общего базового типа, и вы хотите все же объявить в качестве переменной базовый общий класс как универсальный.
Это не имеет смысла.
То, как вы используете на самом деле:

Consumer<ContextA> consumerA = ctx -> methodA(ctx.getItem());
Consumer<ContextB> consumerB = ctx -> methodB(ctx.getItem());

соответствует вашему фактическому API:

public void methodA(ItemA) {..}
public void methodB(ItemB) {..}

Если вы хотите объявить:

Consumer<Context> consumerA = ctx -> methodA(ctx.getItem());
Consumer<Context> consumerB = ctx -> methodB(ctx.getItem());

Вам необходим API, например:

public void methodA(Item) {..}
public void methodB(Item) {..}

В противном случае в качестве альтернативы вы можете, конечно, опускать руки. Но это действительно нежелательно.

Если вы не можете реорганизовать свой API прямо сейчас, вам следует придерживаться фактического дизайна. И если вам действительно нужно сделать свой код более «универсальным» и программировать через интерфейс, вам следует начать рефакторинг шаг за шагом.

0 голосов
/ 04 ноября 2018

Мне кажется, что вы можете использовать универсальный метод для преобразования ваших Item потребителей в Context потребителей. Это может выглядеть примерно так. Не ясно, будет ли это соответствовать вашему требованию, поскольку я не уверен, как вы собираетесь использовать своих потребителей контекста.

public <T extends BaseItem, U extends BaseContext<T>> Consumer<U> wrap(Consumer<T> innerConsumer) {
    return context->innerConsumer.accept(context.getItem());
}

Тогда у вас будет

Consumer<ContextA> consumerA = wrap(this::methodA);
Consumer<ContextB> consumerB = wrap(this::methodB);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...