Non è possibile farlo direttamente in una classe poiché la definizione di classe riportata di seguito non può essere compilata a causa della cancellazione di tipi generici e della dichiarazione dell'interfaccia duplicata.
class TwoTypesConsumer implements Consumer<Apple>, Consumer<Tomato> {
// cannot compile
...
}
Qualsiasi altra soluzione per impacchettare le stesse operazioni di consumo in una classe richiede di definire la classe come:
class TwoTypesConsumer { ... }
che è inutile in quanto è necessario ripetere / duplicare la definizione di entrambe le operazioni e non saranno referenziate dall'interfaccia. Fare IMHO è una brutta duplicazione di codice e piccola che sto cercando di evitare.
Questo potrebbe essere un indicatore anche del fatto che in una classe c'è troppa responsabilità per consumare 2 oggetti diversi (se non sono accoppiati).
Tuttavia, ciò che sto facendo e ciò che puoi fare è aggiungere un oggetto factory esplicito per creare utenti connessi nel modo seguente:
interface ConsumerFactory {
Consumer<Apple> createAppleConsumer();
Consumer<Tomato> createTomatoConsumer();
}
Se in realtà quei tipi sono realmente accoppiati (correlati), consiglierei di creare un'implementazione in questo modo:
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();
}
}
Il vantaggio è che la classe di fabbrica conosce entrambe le implementazioni, esiste uno stato condiviso (se necessario) e, se necessario, è possibile restituire più consumatori accoppiati. Non esiste alcuna dichiarazione del metodo di consumo ripetuta che non sia derivata dall'interfaccia.
Si prega di notare che ogni consumatore potrebbe essere una classe indipendente (ancora privata) se non completamente correlata.
Il rovescio della medaglia di quella soluzione è una complessità di classe superiore (anche se può trattarsi di un file java) e per accedere al metodo di consumo è necessaria un'altra chiamata, invece di:
twoTypesConsumer.consume(apple)
twoTypesConsumer.consume(tomato)
hai:
twoTypesConsumerFactory.createAppleConsumer().consume(apple);
twoTypesConsumerFactory.createTomatoConsumer().consume(tomato);
Per riassumere è possibile definire 2 consumatori generici in una classe di livello superiore utilizzando 2 classi interne, ma in caso di chiamata è necessario innanzitutto ottenere un riferimento al consumatore di implementazione appropriato poiché questo non può essere semplicemente un oggetto consumatore.