Вы не можете сделать это напрямую в одном классе, поскольку приведенное ниже определение класса не может быть скомпилировано из-за стирания общих типов и дублирования объявления интерфейса.
class TwoTypesConsumer implements Consumer<Apple>, Consumer<Tomato> {
// cannot compile
...
}
Любое другое решение для упаковки тех же операций потребления в один класс требует определения вашего класса как:
class TwoTypesConsumer { ... }
что бессмысленно, так как вам нужно повторить / продублировать определение обеих операций, и на них не будут ссылаться из интерфейса. ИМХО, делать это - плохая мелочь и дублирование кода, которого я пытаюсь избежать.
Это также может быть индикатором того, что в одном классе слишком много ответственности, чтобы использовать 2 разных объекта (если они не связаны).
Однако то, что я делаю и что вы можете сделать, это добавить явный объект фабрики для создания подключенных потребителей следующим образом:
interface ConsumerFactory {
Consumer<Apple> createAppleConsumer();
Consumer<Tomato> createTomatoConsumer();
}
Если на самом деле эти типы действительно связаны (связаны), я бы рекомендовал создать реализацию таким образом:
class TwoTypesConsumerFactory {
// shared objects goes here
private class TomatoConsumer implements Consumer<Tomato> {
public void consume(Tomato tomato) {
// you can access shared objects here
}
}
private class AppleConsumer implements Consumer<Apple> {
public void consume(Apple apple) {
// you can access shared objects here
}
}
// It is really important to return generic Consumer<Apple> here
// instead of AppleConsumer. The classes should be rather private.
public Consumer<Apple> createAppleConsumer() {
return new AppleConsumer();
}
// ...and the same here
public Consumer<Tomato> createTomatoConsumer() {
return new TomatoConsumer();
}
}
Преимущество состоит в том, что фабричный класс знает обе реализации, есть общее состояние (при необходимости), и при необходимости вы можете вернуть больше связанных потребителей. Не существует повторяющегося объявления метода потребления, не производного от интерфейса.
Обратите внимание, что каждый потребитель может быть независимым (по-прежнему частным) классом, если они не связаны полностью.
Обратной стороной этого решения является сложность более высокого класса (даже если это может быть один файл java), и для доступа к методу потребления вам понадобится еще один вызов, поэтому вместо:
twoTypesConsumer.consume(apple)
twoTypesConsumer.consume(tomato)
у вас есть:
twoTypesConsumerFactory.createAppleConsumer().consume(apple);
twoTypesConsumerFactory.createTomatoConsumer().consume(tomato);
Подводя итог, вы можете определить 2 общих потребителя в одном классе верхнего уровня, используя 2 внутренних класса, но в случае вызова вам необходимо сначала получить ссылку на соответствующего реализующего потребителя, поскольку этот не может быть просто одним потребительским объектом.
person
kitarek
schedule
29.08.2016