Alternativa dell’eredità multipla in Java

Ho creato due fagioli

class BackPageBean{ String backPage = null; : : : } class InformationMessageBean{ String informationMessage = null; : : : } 

Ora, se una class è a conoscenza di backpage, si estenderà backPageBean, o se deve mostrare qualche tipo di messaggio, quindi estende InformationMessageBean.

 class BackPageAware extends backPageBean{ } class InfoMessAware extends InformationMessageBean{ } someFunction () { if ( theObject instanceOf backPageBean ) { prepareTheBackPage ( theObject.getBackPage() ); } if ( theObject instanceOf InformationMessageBean ) { showtheInformation ( theObject.getMessage() ); } } 

Ora il problema è che se voglio avere un bean che sia sia BackPageAware che InformationAware allora, dato che non abbiamo ereditarietà multipla, quale dovrebbe essere l’approccio?

Giusto per chiarire il mio commento.

Proprio come Darth Eru dice che crei le due interfacce e le due implementazioni predefinite. Quando si ha un bean che ha bisogno di entrambi i comportamenti, la class implementa le due interfacce ma si creano anche variabili delle implementazioni predefinite. In questo modo non hai ancora bisogno di duplicare alcun codice.

  interface InfoMessAware { String getMessage(); } interface BackPageAware { String getBackPage(); } class DefaultInfoMessAware { String getMessage() { return "message"; } } class DefaultBackPageAware { String getBackPage() { return "backPage"; } } class MyBean implements InfoMessAware, BackPageAware { private InfoMessAware messAware = new DefaultInfoMessAware(); private BackPageAware backPageAware = new DefaultBackPageAware(); String getMessage() { return messAware.getMessage(); } String getBackPage() { return backPageAware.getBackPage(); } } 

utilizzare le interfacce:

 interface InfoMessAware { String getMessage(); } interface BackPageAware { String getBackPage(); } class MyBean implements InfoMessAware, BackPageAware { String getMessage() { return "message"; } String getBackPage() { return "backPage"; } } 

quindi sostituire instanceof con le chiamate di metodo standard.

Il problema che stai descrivendo implora l’uso della composizione, non l’ereditarietà. La class essendo BackPageAware significa che conosce quella class / funzionalità. Eredità significa che è una BackPage. Hai descritto una relazione HAS A.

Come è stato detto più volte, utilizzare le interfacce per definire i contratti per il recupero delle informazioni che l’object HA .

Le tue due classi originali dovrebbero essere interfacce, ognuna con un metodo su di esse che recuperi le informazioni che devono essere restituite dall’implementazione.

 public interface BackPageBean { public String getBackPage(); } public interface InformationMessageBean { public String getInformationMessage(); } 

Se vuoi che una class implementa sia BackPageBean che InformationMessageBean, fai semplicemente questo:

 public MyBean implements BackPageBean, InformationMessageBean { public String getBackPage() { return null; } public String getInformationMessage() { return null; } } 

In generale, dovresti evitare di estendere le classi non astratte ogni volta che puoi, questo porta a tutti i tipi di problemi. Invece, prova a utilizzare la composizione anziché l’ereditarietà in cui sono coinvolte le classi concrete e, in caso contrario, prova ad attenersi alle interfacce e alla class astratta occasionale.

Come discusso in altre risposte, l’ereditarietà multipla può essere simulata usando interfacce e composizione, a scapito della necessità di scrivere un sacco di codice boilerplate. Esistono tuttavia numerosi progetti in grado di automatizzarlo sia in fase di compilazione (tramite un pre-processore) che in fase di esecuzione, ad es. Jmixin .

Dichiarare BackPageAware e InformationAware come interfacce, creare classi astratte che implementano tali interfacce per fornire la funzionalità predefinita. Qualsiasi class che deve essere solo una delle due interfacce può ereditare la corrispondente class astratta. Una class che deve essere entrambe può ereditare una delle classi astratte e implementare l’altra interfaccia, o implementare entrambe le interfacce, qualunque sia. Se non ci sono funzionalità di default, allora non hai nemmeno bisogno delle classi astratte.

Non è ansible estendere più classi ma è ansible implementare più interfacce. Ricorda che quando si applica un’interfaccia a una class, l’object della class ha una relazione IS-A con l’interfaccia.

È ansible avere BackPageAware e InformationAware come interfacce anziché come classi. Ciò consente di recuperare i messaggi da entrambe le interfacce nel caso in cui il “bean” a cui si fa riferimento sia di BackPageAware e InformationAware .

 public class Name implements BackPageAware, InformationAware {}