Devo implementare direttamente un'interfaccia o far eseguire la superclasse?

13

C'è una differenza tra

public class A extends AbstractB implements C
{...}

vs ...

public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}

Capisco che in entrambi i casi, la classe A finirà per conformarsi all'interfaccia. Nel secondo caso, AbstractB può fornire l'implementazione per i metodi di interfaccia in C . È questa l'unica differenza?

Se NON desidero fornire un'implementazione per nessuno dei metodi di interfaccia in AbstractB , quale stile dovrei utilizzare ? L'uso dell'uno o dell'altro ha uno scopo nascosto di "documentazione"?

    
posta c_maker 19.12.2012 - 03:12
fonte

3 risposte

18

Tutto dipende da se AbstractB implements C semanticamente. I.e se ha senso semanticamente per AbstractB per implementare C , quindi vai a farlo.

Se prendiamo esempi concreti, la differenza semantica diventa chiara.

Se A = Cane, AstrattoB = Animale, C = IBark

Solo una scelta sensata è

class Dog extends Animal implements IBark{

Questo non ha senso, poiché ciò implicherebbe che tutti gli animali abbaiano.

class Animal implements IBark{

Le altre differenze entrano in gioco se hai più di un class A che eredita da AbstractB . In # 1 non è necessario implementare C, in # 2 sono tutti costretti a implementare C.

    
risposta data 19.12.2012 - 03:26
fonte
2

Il modo semplice per determinare la relazione di ereditarietà corretta non è guardare le classi stesse, ma il codice che chiama metodi su quelle classi. Da qualche parte nel tuo codice hai qualcosa come AbstractB b = new A(); o otherObject.addAbstractB(this); . In entrambi i casi, in seguito utilizzerai il riferimento AbstractB per effettuare varie chiamate al metodo.

In questa situazione, vuoi chiamare i metodi di C ? Se è così, AbstractB dovrebbe implementare C . In caso contrario, non dovrebbe. Se non hai situazioni del genere, allora non hai bisogno di ereditarietà e dovresti rifattorici invece di usare la composizione perché è molto più sciolto.

    
risposta data 19.12.2012 - 05:17
fonte
2

Non è uno scopo di documentazione "nascosto". Ti permette di lanciare AbstractB e tutte le sue sottoclassi in C. Esistono in realtà tre stili.

public class A extends AbstractB implements C
public class AbstractB

Lo userei se AbstractB non implementasse logicamente C. Anche se non fornisce i metodi, potrebbe avere un significato. Come ad esempio Dog estende gli strumenti Animal Wag. Non ha senso per tutti gli animali di Wag. Si noti che questo approccio in realtà non preclude a AbstractB di fornire l'implementazione.

public class A extends AbstractB
public AbstractB implements C

Lo userei se volessi che tutte le sottoclassi implementassero l'interfaccia E ha senso che tutti lo facciano. Come Beagle estende AbstractDog implementa Wag.

public class A extends AbstractB implements C
public class AbstractB implements C

Questo è ridondante ma potrebbe aggiungere chiarezza.

    
risposta data 19.12.2012 - 03:33
fonte

Leggi altre domande sui tag