2009-06-24 19 views
8

Ho creato due chicchialternativa di ereditarietà multipla in Java

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


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

Ora, se una classe è backpage a conoscenza allora si estenderà backPageBean, o se ha bisogno di mostrare un qualche tipo di messaggio, allora si 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 è, se voglio avere un fagiolo che è sia BackPageAware così come InformationAware allora, come non abbiamo l'ereditarietà multipla, quello che dovrebbe essere l'approccio?

+3

È Java. Non JAVA. –

+1

non l'ho mai saputo, thnx: D –

risposta

9

Giusto per chiarire il mio commento.

Proprio come Darth Eru dice si creano le due interfacce e le due di default implementazioni. Quando hai un bean che richiede entrambi i comportamenti, la tua classe è che implementa le due interfacce ma crei anche le variabili delle implementazioni predefinite . In questo modo è ancora non è necessario 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(); 
     } 
    } 
+0

Perché 'DefaultInfoMessAware' e' DefaultBackPageAware' non implementano rispettivamente le interfacce 'InfoMessAware' e' BackPageAware'? –

11

uso 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 chiamate di metodi standard.

+1

Ciò significa certamente che dovrò avere la (stessa) definizione di getbackpage e getMessage in tutte le classi che implementeranno queste interfacce. string getMessage() { return this.message; } // avremo un setter anche String getbackPage() { ritorno this.backPage; } // avremo un setter anche –

+0

sfortunatamente Java ha ereditarietà multipla solo per le interfacce – dfa

0

Dichiarare BackPageAware e InformationAware come interfacce, creare classi astratte che implementano tali interfacce per fornire la funzionalità predefinita. Qualsiasi classe che deve essere solo una delle due interfacce può ereditare la corrispondente classe astratta. Una classe 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.

+1

Se una classe ha bisogno di entrambi i comportamenti, implementerei le interfacce e delegheremo alle implementazioni predefinite. Has-A rocks :) – willcodejavaforfood

+0

ti piacerebbe elaborare il codice? –

+0

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 classe implementa le due interfacce ma si creano anche variabili delle implementazioni predefinite. In questo modo non hai ancora bisogno di duplicare alcun codice. – willcodejavaforfood

0

Non è possibile estendere più classi ma è possibile implementare più interfacce. Ricorda che quando si applica un'interfaccia a una classe, l'oggetto della classe ha una relazione IS-A con l'interfaccia.

8

Il problema che stai descrivendo implora l'uso della composizione, non l'ereditarietà. La classe essendo BackPageAware significa che conosce quella classe/funzionalità. Ereditarietà significa che IS a BackPage. Hai descritto una relazione HAS A.

Come è stato detto più volte, utilizzare le interfacce per definire i contratti per il recupero delle informazioni dell'oggetto HAS.

1

I suoi due classi originali dovrebbero essere Interfacce, ognuno con un metodo su di loro che recupera le informazioni che le implementazioni dovrebbero tornare.

public interface BackPageBean { 
    public String getBackPage(); 
} 


public interface InformationMessageBean { 
    public String getInformationMessage(); 
} 

Se si desidera una classe per implementare sia BackPageBean e InformationMessageBean semplicemente fanno questo:

public MyBean implements BackPageBean, InformationMessageBean { 

    public String getBackPage() { 
    return null; 
    } 

    public String getInformationMessage() { 
    return null; 
    } 
} 

In generale, si dovrebbe evitare di estendere le classi non astratte ogni volta che potete, 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 classe astratta occasionale.

1

Come discusso in altre risposte, l'ereditarietà multipla può essere simulata utilizzando 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 esempio jmixin.

+0

+1 per indicare la necessità di scrivere molto [codice boilerplate] (https://en.wikipedia.org/wiki/Boilerplate_code), che è un'omissione sorprendentemente frequente nel consiglio "preferisci la composizione sull'ereditarietà", rendendo così la tecnica sembra un'alternativa senza perdite all'ereditarietà mentre non lo è assolutamente. – SantiBailors

0

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

public class Name implements BackPageAware, InformationAware {}