joanna
joanna

Reputation: 773

Java call non-generic method from generic method

I'm trying to refactor something. I have the following class hierarchy:

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> {..}

And 2 methods that a consumer needs to use:

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

Is it somehow possible to have a generic Consumer for these 2 methods ? Right now, I have 2 non-generic ones:

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

I would say this is not possible due to type erasure, I just want to make sure

Upvotes: 1

Views: 127

Answers (2)

Dawood ibn Kareem
Dawood ibn Kareem

Reputation: 79808

It seems to me that you could use a generic method to convert your Item consumers into Context consumers. It might look something like this. It's not clear whether this would meet your requirement, as I'm not sure how you intend to use your context consumers.

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

You'd then have

Consumer<ContextA> consumerA = wrap(this::methodA);
Consumer<ContextB> consumerB = wrap(this::methodB);

Upvotes: 1

davidxxx
davidxxx

Reputation: 131324

The 2 methods expect specific subtypes of Item not the common base type and you want to all the same declare as variable the base common class as generic.
That makes no sense.
The way you use actually :

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

is conform to your actual API :

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

If you want to declare :

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

You need an API such as :

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

Otherwise as alternative you can of course downcast. But that is really undesirable.

If you cannot refactor your API right now, you should stay to the actual design. And if you really need to make your code more "generic" and to program by interface you should start refactoring step by step.

Upvotes: 0

Related Questions