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


14

C'è una differenza tra

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

contro...

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, AbstractBpuò fornire l'implementazione per i metodi di interfaccia in C. Questa è l'unica differenza?

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


3
suggerimento sul titolo: dovrei implementare direttamente un'interfaccia o fare in modo che la superclasse lo faccia
Jeanne Boyarsky,

Risposte:


20

Tutto dipende se AbstractB implements Csemanticamente. Vale a dire se ha senso semanticamente AbstractBimplementarlo C, quindi provaci.

Se prendiamo esempi concreti, la differenza semantica diventa chiara.

Se A = Cane, Astratto B = Animale, C = IBark

L'unica 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 qualcosa di più che class Aereditare da AbstractB. Nel n. 1 non è necessario implementare C, nel n. 2 sono tutti costretti a implementare C.


1
+1 Molto più chiaro della mia risposta!
Hand-E-Food,

Inoltre, se l'interfaccia fosse Heterotroph, sembra ragionevole Animalimplementare Heterotroph. Se ti aspetti molti altri animali che abbaiano e vuoi trattarli allo stesso modo, un'altra classe BarkingAnimal extends Animal implements IBarksarebbe la strada da percorrere.
scarfridge,

@scarfridge In realtà mi aspetterei che l'animale si estenda, Heterotrophma grazie per il tuo contributo
Karthik T

2

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

In quella situazione, hai intenzione di chiamare metodi di C? Se è così, allora AbstractBdovrebbe implementare C. In caso contrario, non dovrebbe. Se non hai situazioni del genere, allora non hai bisogno di ereditarietà e dovresti rifattorizzare l'uso della composizione perché è molto più libero.


2

Non è uno scopo di documentazione "nascosto". Ti permette di lanciare AbstractB e tutte le sue sottoclassi su C. In realtà ci sono tre stili.

public class A extends AbstractB implements C
public class AbstractB

Userei questo se AbstractB non implementasse logicamente C. Anche se non fornisce i metodi, potrebbe avere un significato. Come Dog estende Animal implementa Wag. Non ha senso scuotere tutti gli animali. Si noti che questo approccio in realtà non impedisce a AbstractB di fornire l'implementazione.

public class A extends AbstractB
public AbstractB implements C

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

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

Questo è ridondante ma potrebbe aggiungere chiarezza.


Penso che "AbstractC" (che non esiste nella domanda) nel secondo paragrafo dovrebbe essere cambiato in "AbstractB". Non posso modificare per farlo poiché gli editori devono essere almeno 6 caratteri.
cellepo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.