2016-06-15 49 views
23

Ho un paio di interfacce:Come faccio ad accettare un metodo con istanze con due interfacce?

public interface Speaker { 
    void speak(); 
} 

public inteface Walker { 
    void walk(); 
} 

Voglio un metodo che prende le istanze che sono sia un Speaker e Walker.

Ora, potrei implementare un'altra interfaccia:

public interface WalkerSpeaker extends Walker, Speaker { 

} 

e accetta che:

void walkAndTalk(final WalkerSpeaker x) { 
    x.walk(); 
    x.speak(); 
} 

Ma questo è abbastanza ingombrante con molte combinazioni, e ogni implementazione deve ereditare da WalkerSpeaker per farlo funzionare !

C'è un modo migliore?

+1

Questo è praticamente come è. Se diventa ingombrante, potresti voler guardare il tuo disegno. – Underbalanced

+2

@Ravindrababu la tua risposta a tale link è altrettanto ingombrante e molto rigida che non può essere ampliata o modificata facilmente. – Underbalanced

+0

fyi: È buona norma usare 'implements' invece di' extends' per le interfacce. – Akunosh

risposta

53

È possibile raggiungere questo obiettivo con generici come segue

public <T extends Speaker & Walker> void walkAndTalk(T x) { 
    x.walk(); 
    x.speak(); 
} 

Il tipo di parametro T sarà "doppio-delimitata" per entrambe le interfacce, quindi in sostanza T sarà un WalkerSpeaker tranne che non devi scrivere un'interfaccia separata per questo.

+0

Perfetto. C'è qualche sovraccarico a questo v.s. usando un'interfaccia extra? Immagino non a causa della cancellazione del tipo. – sdgfsdh

+3

Poiché i generici vengono cancellati in fase di compilazione, no non c'è. Non che importi, dal momento che le prestazioni sono un problema più grande rispetto ad alcune chiamate al metodo casuale. – Kayaman

+4

+1, idea molto carina per questa soluzione, ma non mi piace l'idea che un oggetto possa essere visto con due nature diverse nello stesso metodo. Sembra che il metodo walkAndTalk abbia più di una responsabilità, quindi infrange il principio della Single Responsibility. –

Problemi correlati