Interfaccia contro class base

Quando dovrei usare un’interfaccia e quando dovrei usare una class base?

Dovrebbe essere sempre un’interfaccia se non voglio realmente definire un’implementazione di base dei metodi?

Se ho una class di cani e gatti. Perché dovrei voler implementare IPet al posto di PetBase? Posso capire di avere interfacce per ISh o IBark (IMakesNoise?), Perché possono essere posizionate su base pet per animale domestico, ma non capisco quale usare per un Pet generico.

Prendiamo il tuo esempio di una class Dog and a Cat, e illustriamo usando C #:

Sia un cane che un gatto sono animali, in particolare, mammiferi quadrupedi (gli animali sono troppo generici). Supponiamo che tu abbia un Mammifero di class astratta, per entrambi:

public abstract class Mammal 

Questa class base avrà probabilmente metodi predefiniti come:

  • Alimentazione
  • Compagno

Tutto questo è un comportamento che ha più o meno la stessa implementazione tra le due specie. Per definire questo avrai:

 public class Dog : Mammal public class Cat : Mammal 

Supponiamo che ci siano altri mammiferi, che vedremo di solito in uno zoo:

 public class Giraffe : Mammal public class Rhinoceros : Mammal public class Hippopotamus : Mammal 

Questo sarà comunque valido perché al centro della funzionalità Feed() e Mate() rimarranno gli stessi.

Tuttavia, le giraffe, i rinoceronti e gli ippopotami non sono esattamente degli animali da cui si possono creare animali domestici. Ecco dove sarà utile un’interfaccia:

 public interface IPettable { IList Tricks{get; set;} void Bathe(); void Train(Trick t); } 

L’implementazione per il contratto di cui sopra non sarà la stessa tra un gatto e un cane; mettere le loro implementazioni in una class astratta per ereditare sarà una ctriggers idea.

Le tue definizioni Dog and Cat dovrebbero ora apparire come:

 public class Dog : Mammal, IPettable public class Cat : Mammal, IPettable 

Teoricamente puoi scavalcarli da una class base più alta, ma essenzialmente un’interfaccia ti consente di aggiungere solo le cose che ti servono in una class senza bisogno di ereditarietà.

Di conseguenza, poiché in genere è ansible ereditare solo da una class astratta (nella maggior parte dei linguaggi OO tipizzati staticamente, ad esempio … eccezioni include C ++) ma essere in grado di implementare più interfacce, consente di build oggetti in modo strettamente necessario .

Bene, Josh Bloch si è detto in Effective Java 2d :

Preferisci interfacce su classi astratte

Alcuni punti principali:

  • Le classi esistenti possono essere facilmente adattate per implementare una nuova interfaccia . Tutto ciò che devi fare è aggiungere i metodi richiesti se ancora non esistono e aggiungere una clausola implements alla dichiarazione della class.

  • Le interfacce sono ideali per la definizione di mix . In parole povere, un mixin è un tipo che una class può implementare in aggiunta al suo “tipo primario” per dichiarare che fornisce un comportamento facoltativo. Ad esempio, Comparable è un’interfaccia mixin che consente a una class di dichiarare che le sue istanze sono ordinate rispetto ad altri oggetti comparabili tra loro.

  • Le interfacce consentono la costruzione di framework di tipo non gerarchico . Le gerarchie di tipo sono ottime per l’organizzazione di alcune cose, ma altre cose non rientrano ordinatamente in una gerarchia rigida.

  • Le interfacce consentono miglioramenti di funzionalità sicuri e potenti tramite l’idioma della class wrapper. Se si utilizzano classi astratte per definire i tipi, si lascia il programmatore che desidera aggiungere funzionalità senza alternative ma utilizzare l’ereditarietà.

Inoltre, è ansible combinare le virtù delle interfacce e delle classi astratte fornendo una class di implementazione scheletrica astratta da utilizzare con ogni interfaccia non banale che si esporta.

D’altra parte, le interfacce sono molto difficili da evolvere. Se aggiungi un metodo a un’interfaccia, interromperà tutte le sue implementazioni.

PS .: Compra il libro. È molto più dettagliato.

Lo stile moderno è quello di definire IPet e PetBase.

Il vantaggio dell’interfaccia è che l’altro codice può usarlo senza legami di sorta con altri codici eseguibili. Completamente “pulito”. Anche le interfacce possono essere mescolate.

Ma le classi base sono utili per implementazioni semplici e utilità comuni. Quindi fornisci anche una class base astratta per risparmiare tempo e codice.

Le interfacce e le classi base rappresentano due diverse forms di relazione.

L’ereditarietà (classi base) rappresenta una relazione “è-a”. Ad esempio un cane o un gatto “è un animale domestico”. Questa relazione rappresenta sempre lo scopo (singolo) della class (in congiunzione con il “principio di responsabilità unica” ).

Le interfacce , d’altra parte, rappresentano funzionalità aggiuntive di una class. Lo chiamerei una relazione “è”, come in ” Foo is disposable”, quindi l’interfaccia IDisposable in C #.

interfacce

  • Definisce il contratto tra 2 moduli. Non può avere alcuna implementazione.
  • La maggior parte delle lingue consente di implementare più interfacce
  • La modifica di un’interfaccia è un cambio di rottura. Tutte le implementazioni devono essere ricompilate / modificate.
  • Tutti i membri sono pubblici. Le implementazioni devono implementare tutti i membri.
  • Le interfacce aiutano nel disaccoppiamento. È ansible utilizzare i framework mock per prendere in giro qualsiasi cosa dietro un’interfaccia
  • Le interfacce normalmente indicano un tipo di comportamento
  • Le implementazioni dell’interfaccia sono disaccoppiate / isolate l’una dall’altra

Classi base

  • Ti consente di aggiungere alcune implementazioni predefinite ottenute gratuitamente tramite derivazione
  • Tranne C ++, puoi solo derivare da una class. Anche se potrebbe da più classi, di solito è una ctriggers idea.
  • Cambiare la class base è relativamente facile. Le derivazioni non devono fare nulla di speciale
  • Le classi base possono dichiarare funzioni protette e pubbliche alle quali è ansible accedere tramite derivazioni
  • Le astratte classi base non possono essere facilmente derise come le interfacce
  • Le classi base normalmente indicano la gerarchia di tipi (IS A)
  • Le derivazioni di class possono dipendere da alcuni comportamenti di base (avere una conoscenza complessa dell’implementazione dei genitori). Le cose possono essere complicate se si apportano modifiche all’implementazione di base per un ragazzo e si rompono gli altri.

In generale, dovresti favorire le interfacce su classi astratte. Una ragione per usare una class astratta è se hai un’implementazione comune tra le classi concrete. Naturalmente, dovresti comunque dichiarare un’interfaccia (IPet) e avere una class astratta (PetBase) implementare quell’interfaccia. Usando interfacce piccole e distinte, puoi usare i multipli per migliorare ulteriormente la flessibilità. Le interfacce consentono la massima flessibilità e portabilità dei tipi oltre i limiti. Quando si passano i riferimenti oltre i limiti, passare sempre l’interfaccia e non il tipo concreto. Ciò consente al destinatario di determinare l’implementazione concreta e offre la massima flessibilità. Questo è assolutamente vero quando si programma in modo TDD / BDD.

La Gang of Four ha dichiarato nel loro libro “Poiché l’ereditarietà espone una sottoclass ai dettagli dell’implementazione dei suoi genitori, si dice spesso che” l’ereditarietà rompe l’incapsulamento “. Credo che questo sia vero.

Questo è piuttosto specifico per .NET, ma il manuale Framework Design Guidelines sostiene che in generale le classi danno maggiore flessibilità in un framework in evoluzione. Una volta che un’interfaccia è stata spedita, non si ha la possibilità di cambiarla senza rompere il codice che ha usato quell’interfaccia. Con una class tuttavia, è ansible modificarlo e non interrompere il codice che si collega ad esso. Finché apporterai le giuste modifiche, inclusa l’aggiunta di nuove funzionalità, sarai in grado di estendere ed evolvere il tuo codice.

Krzysztof Cwalina dice a pagina 81:

Nel corso delle tre versioni di .NET Framework, ho parlato di questa linea guida con un discreto numero di sviluppatori nel nostro team. Molti di loro, compresi quelli che inizialmente non erano d’accordo con le linee guida, hanno detto che si sono pentiti di aver fornito alcune API come interfaccia. Non ho sentito nemmeno un caso in cui qualcuno si sia rammaricato di aver spedito una class.

Detto questo, c’è sicuramente un posto per le interfacce. Come linea guida generale, fornire sempre un’implementazione astratta di una class base di un’interfaccia se non altro come esempio di un modo per implementare l’interfaccia. Nel migliore dei casi quella class base farà risparmiare un sacco di lavoro.

Juan,

Mi piace pensare alle interfacce come a un modo per caratterizzare una class. Una particolare class di razza di cani, ad esempio uno YorkshireTerrier, può essere una discendente della class del cane genitore, ma è anche implementata da IFurry, IStubby e IYippieDog. Quindi la class definisce ciò che è la class, ma l’interfaccia ci dice cose a riguardo.

Il vantaggio di questo è che mi permette, per esempio, di riunire tutti gli IYippieDog e di buttarli nella mia collezione Ocean. Così ora posso raggiungere un particolare insieme di oggetti e trovarne quelli che soddisfano i criteri che sto osservando senza ispezionare la class troppo da vicino.

Trovo che le interfacce dovrebbero davvero definire un sottoinsieme del comportamento pubblico di una class. Se definisce tutto il comportamento pubblico per tutte le classi che implementano, di solito non ha bisogno di esistere. Non mi dicono niente di utile.

Questo pensiero però va contro l’idea che ogni class dovrebbe avere un’interfaccia e dovresti codificare l’interfaccia. Va bene, ma si finisce con un sacco di interfacce uno a uno per le classi e questo rende le cose confuse. Capisco che l’idea è che non costa davvero nulla da fare e ora puoi scambiare le cose dentro e fuori con facilità. Tuttavia, trovo che raramente lo faccio. La maggior parte delle volte sto solo modificando la class esistente e ho esattamente gli stessi problemi che ho sempre fatto se l’interfaccia pubblica di quella class ha bisogno di essere modificata, tranne che ora devo cambiarla in due punti.

Quindi se pensi come me diresti sicuramente che Cat and Dog è IPettable. È una caratterizzazione che li combina entrambi.

L’altro pezzo di questo però dovrebbe avere la stessa class base? La domanda è che hanno bisogno di essere trattati in generale come la stessa cosa. Certamente sono entrambi animali, ma è così adatto a come li useremo insieme.

Diciamo che voglio riunire tutte le classi di Animali e metterle nel mio contenitore dell’Arca.

O hanno bisogno di essere mammiferi? Forse abbiamo bisogno di una specie di fabbrica di mungitura di animali incrociati?

Hanno addirittura bisogno di essere collegati insieme? Basta sapere che sono entrambi IPettable?

Spesso sento il desiderio di derivare un’intera gerarchia di classi quando ho davvero bisogno di una sola class. Lo faccio in anticipo un giorno potrei averne bisogno e di solito non lo faccio mai. Anche quando lo faccio, di solito trovo che devo fare molto per sistemarlo. Questo perché la prima class che sto creando non è il Cane, non sono così fortunato, è invece l’ornitorinco. Ora la mia intera gerarchia di classi si basa sul caso bizzarro e ho un sacco di codice sprecato.

A un certo punto potresti anche scoprire che non tutti i gatti sono IPettable (come quello senza capelli). Ora puoi spostare quell’interfaccia in tutte le classi derivative che si adattano. Scoprirai che un cambiamento molto meno grave che tutti i gatti improvvisi non derivano più da PettableBase.

Ecco la definizione base e semplice dell’interfaccia e della class base:

  • Classe base = ereditarietà di oggetti.
  • Interfaccia = ereditarietà funzionale.

Saluti

Raccomando di usare la composizione invece dell’ereditarietà ogni volta che è ansible. Usa le interfacce ma usa gli oggetti membro per l’implementazione di base. In questo modo, puoi definire una fabbrica che costruisce i tuoi oggetti a comportarsi in un certo modo. Se si desidera modificare il comportamento, si crea un nuovo metodo factory (o factory astratto) che crea diversi tipi di oggetti secondari.

In alcuni casi, potresti scoprire che i tuoi oggetti primari non hanno bisogno di interfacce, se tutti i comportamenti mutabili sono definiti negli oggetti helper.

Quindi, invece di IPet o PetBase, si potrebbe finire con un animale domestico che ha un parametro IFurBehavior. Il parametro IFurBehavior è impostato dal metodo CreateDog () di PetFactory. È questo parametro che viene chiamato per il metodo shed ().

Se lo fai, troverai che il tuo codice è molto più flessibile e la maggior parte dei tuoi oggetti semplici si occupa di comportamenti di base su tutto il sistema.

Raccomando questo modello anche nei linguaggi di ereditarietà multipla.

Ha spiegato bene in questo articolo di Java World

Personalmente tendo ad usare le interfacce per definire le interfacce, cioè parti del design del sistema che specificano in che modo si dovrebbe accedere a qualcosa.

Non è raro che avrò una class che implementa 1 o più interfacce.

Classi astratte che uso come base per qualcos’altro.

Quello che segue è un estratto dell’articolo sopra menzionato articolo JavaWorld.com, autore Tony Sintes, 20/04/01


Interfaccia contro class astratta

La scelta di interfacce e classi astratte non è né una né una proposizione. Se hai bisogno di cambiare il tuo design, crea un’interfaccia. Tuttavia, potresti avere classi astratte che forniscono un comportamento predefinito. Le classi astratte sono candidati eccellenti all’interno di quadri applicativi.

Le classi astratte consentono di definire alcuni comportamenti; costringono le tue sottoclassi a fornirne altre. Ad esempio, se si dispone di un framework di applicazione, una class astratta può fornire servizi predefiniti come la gestione di eventi e messaggi. Questi servizi consentono alla tua applicazione di collegarsi al framework dell’applicazione. Tuttavia, alcune funzionalità specifiche dell’applicazione possono essere eseguite solo dall’applicazione. Tale funzionalità potrebbe includere attività di avvio e arresto, che sono spesso dipendenti dall’applicazione. Quindi, invece di provare a definire quel comportamento stesso, la class base astratta può dichiarare metodi di arresto e avvio astratti. La class base sa che ha bisogno di questi metodi, ma una class astratta consente alla class di ammettere che non sa come eseguire tali azioni; sa solo che deve iniziare le azioni. Quando è il momento di avviarsi, la class astratta può chiamare il metodo di avvio. Quando la class base chiama questo metodo, Java chiama il metodo definito dalla class figlio.

Molti sviluppatori dimenticano che una class che definisce un metodo astratto può chiamare anche quel metodo. Le classi astratte sono un modo eccellente per creare gerarchie di ereditarietà pianificate. Sono anche una buona scelta per le classi non-foglia nelle gerarchie di classi.

Classe contro interfaccia

Alcuni dicono che dovresti definire tutte le classi in termini di interfacce, ma penso che la raccomandazione sia un po ‘estrema. Uso le interfacce quando vedo che qualcosa nel mio design cambierà frequentemente.

Ad esempio, il modello Strategia consente di scambiare nuovi algoritmi e processi nel programma senza alterare gli oggetti che li utilizzano. Un lettore multimediale potrebbe sapere come riprodurre CD, MP3 e file wav. Ovviamente, non si desidera codificare manualmente tali algoritmi di riproduzione nel lettore; questo renderà difficile aggiungere un nuovo formato come AVI. Inoltre, il tuo codice sarà disseminato di dichiarazioni caso inutili. E per aggiungere la beffa al danno, è necessario aggiornare tali dichiarazioni caso ogni volta che si aggiunge un nuovo algoritmo. Tutto sumto, questo non è un modo molto orientato agli oggetti per programmare.

Con il modello di strategia, puoi semplicemente incapsulare l’algoritmo dietro un object. Se lo fai, puoi fornire nuovi plug-in multimediali in qualsiasi momento. Chiamiamo la class plug-in MediaStrategy. Quell’object avrebbe un metodo: playStream (Stream s). Quindi, per aggiungere un nuovo algoritmo, estendiamo semplicemente la nostra class algoritmica. Ora, quando il programma incontra il nuovo tipo di media, si limita a debind la riproduzione dello stream alla nostra strategia media. Naturalmente, avrai bisogno di qualche impianto idraulico per istanziare correttamente le strategie dell’algoritmo di cui avrai bisogno.

Questo è un posto eccellente per usare un’interfaccia. Abbiamo utilizzato il modello di strategia, che indica chiaramente un luogo nel design che cambierà. Pertanto, dovresti definire la strategia come un’interfaccia. In generale, dovresti preferire le interfacce all’ereditarietà quando vuoi che un object abbia un determinato tipo; in questo caso, MediaStrategy. Affidarsi all’eredità per l’id quadro del tipo è pericoloso; ti blocca in una particolare gerarchia ereditaria. Java non consente l’ereditarietà multipla, quindi non è ansible estendere qualcosa che ti dà un’implementazione utile o più tipi di id quadro.

Tieni anche presente che non devi essere spazzato via in OO ( vedi blog ) e modellare sempre gli oggetti in base al comportamento richiesto, se stavi progettando un’app in cui l’unico comportamento richiesto era un nome generico e una specie per un animale, di cui avresti solo bisogno un animale di class con una proprietà per il nome, invece di milioni di classi per ogni ansible animale nel mondo.

Ho una regola approssimativa

Funzionalità: probabilmente diversa in tutte le parti: interfaccia.

Dati e funzionalità, le parti saranno per lo più le stesse, parti diverse: class astratta.

Dati e funzionalità, in realtà funzionanti, se esteso solo con lievi modifiche: class ordinaria (concreta)

Dati e funzionalità, nessuna modifica pianificata: class ordinaria (concreta) con modificatore finale.

Dati e forse funzionalità: sola lettura: membri di enum.

Questo è molto approssimativo e pronto e non del tutto rigorosamente definito, ma c’è uno spettro dalle interfacce in cui tutto è destinato a essere modificato in enumerazioni in cui tutto è fissato un po ‘come un file di sola lettura.

Le interfacce dovrebbero essere piccole. Davvero piccolo Se stai davvero abbattendo gli oggetti, le tue interfacce probabilmente conterranno solo alcuni metodi e proprietà molto specifici.

Le lezioni astratte sono scorciatoie. Ci sono cose che condividono tutti i derivati ​​di PetBase che puoi codificare una sola volta e farla finita? Se sì, allora è il momento di una lezione astratta.

Anche le classi astratte sono limitanti. Mentre ti danno una grande scorciatoia per produrre oggetti figlio, qualsiasi object dato può solo implementare una class astratta. Molte volte, trovo questa una limitazione delle classi Abstract, ed è per questo che utilizzo molte interfacce.

Le classi astratte possono contenere diverse interfacce. La tua class astratta PetBase può implementare IPet (gli animali domestici hanno proprietari) e IDigestion (gli animali domestici mangiano, o almeno dovrebbero). Tuttavia, PetBase probabilmente non implementerà IMammal, dal momento che non tutti gli animali domestici sono mammiferi e non tutti i mammiferi sono animali domestici. Puoi aggiungere un MammalPetBase che estende PetBase e aggiungi IMammal. FishBase potrebbe avere PetBase e aggiungere IFish. IFish avrebbe ISwim e IUnderwaterBreather come interfacce.

Sì, il mio esempio è estesamente complicato per il semplice esempio, ma questo fa parte del bello di come le interfacce e le classi astratte funzionano insieme.

Il caso delle Classi Base rispetto alle Interfacce è stato ben illustrato nelle Linee guida per la codifica .NET di Submain:

Classi di base e interfacce Un tipo di interfaccia è una descrizione parziale di un valore, potenzialmente supportato da molti tipi di object. Utilizzare le classi di base anziché le interfacce quando ansible. Dal punto di vista della versione, le classi sono più flessibili delle interfacce. Con una class, è ansible fornire la versione 1.0 e quindi nella versione 2.0 aggiungere un nuovo metodo alla class. Finché il metodo non è astratto, tutte le classi derivate esistenti continuano a funzionare invariate.

Poiché le interfacce non supportano l’ereditarietà dell’implementazione, il modello applicato alle classi non si applica alle interfacce. Aggiungere un metodo a un’interfaccia equivale ad aggiungere un metodo astratto a una class base; qualsiasi class che implementa l’interfaccia si interromperà perché la class non implementa il nuovo metodo. Le interfacce sono appropriate nelle seguenti situazioni:

  1. Diverse classi non correlate vogliono supportare il protocollo.
  2. Queste classi hanno già delle classi base stabilite (ad esempio, alcuni sono controlli dell’interfaccia utente (UI) e alcuni sono servizi Web XML).
  3. L’aggregazione non è appropriata o praticabile. In tutte le altre situazioni, l’ereditarietà delle classi è un modello migliore.

Una differenza importante è che puoi ereditare solo una class base, ma puoi implementare molte interfacce. Pertanto, si desidera utilizzare solo una class base se si è assolutamente certi che non sarà necessario ereditare anche una class base diversa. Inoltre, se trovi che la tua interfaccia sta diventando grande, dovresti iniziare a cercare di suddividerla in pochi elementi logici che definiscono funzionalità indipendenti, poiché non esiste una regola che la tua class non possa implementarle tutte (o che tu possa definire una diversa interfaccia che li eredita tutti per raggrupparli).

Quando ho iniziato a studiare la programmazione orientata agli oggetti, ho commesso l’errore facile e probabilmente comune dell’utilizzo dell’ereditarietà per condividere comportamenti comuni, anche laddove tale comportamento non era essenziale per la natura dell’object.

Per sviluppare ulteriormente un esempio molto usato in questa particolare domanda, ci sono molte cose che possono essere richieste – fidanzate, macchine, coperte fuzzy … – quindi avrei potuto avere una class Petable che forniva questo comportamento comune, e varie classi ereditavano da.

Tuttavia, essere petabili non fa parte della natura di nessuno di questi oggetti. Ci sono concetti molto più importanti che sono essenziali per la loro natura: la ragazza è una persona, l’auto è un veicolo terrestre, il gatto è un mammifero …

I comportamenti devono essere assegnati prima alle interfacce (compresa l’interfaccia predefinita della class) e promossi a una class base solo se sono (a) comuni a un grande gruppo di classi che sono sottoinsiemi di una class più grande – nello stesso senso che “gatto” e “persona” sono sottoinsiemi di “mammifero”.

Il problema è che, dopo aver compreso un design orientato agli oggetti sufficientemente migliore di quello che ho fatto all’inizio, lo farai normalmente senza nemmeno pensarci. Quindi la nuda verità dell’affermazione “codice per un’interfaccia, non una class astratta” diventa così ovvio che hai difficoltà a credere che qualcuno si debba prendere la briga di dirlo – e iniziare a provare a leggere altri significati in esso.

Un’altra cosa che aggiungerei è che se una class è puramente astratta – senza membri non astratti, non ereditati o metodi esposti a figlio, padre o cliente – allora perché è una class? Potrebbe essere sostituito, in alcuni casi, da un’interfaccia e in altri casi da Null.

Fonte : http://jasonroell.com/2014/12/09/interfaces-vs-abstract-classs-what-should-you-use/

C # è un linguaggio meraviglioso che è maturato e si è evoluto negli ultimi 14 anni. Questo è fantastico per noi sviluppatori perché un linguaggio maturo ci fornisce una pletora di funzionalità linguistiche che sono a nostra disposizione.

Tuttavia, con molto potere diventa molta responsabilità. Alcune di queste funzionalità possono essere utilizzate in modo improprio o, a volte, è difficile capire perché scegliere una funzione rispetto a un’altra. Nel corso degli anni, una caratteristica che ho visto molti sviluppatori lottare è quando scegliere di utilizzare un’interfaccia o scegliere di utilizzare una class astratta. Entrambi presentano vantaggi e svantaggi e l’ora e il luogo corretti da utilizzare ciascuno. Ma come decidere ???

Entrambi prevedono il riutilizzo di funzionalità comuni tra i tipi. The most obvious difference right away is that interfaces provide no implementation for their functionality whereas abstract classs allow you to implement some “base” or “default” behavior and then have the ability to “override” this default behavior with the classs derived types if necessary.

This is all well and good and provides for great reuse of code and adheres to the DRY (Don’t Repeat Yourself) principle of software development. Abstract classs are great to use when you have an “is a” relationship.

For example: A golden retriever “is a” type of dog. So is a poodle. They both can bark, as all dogs can. However, you might want to state that the poodle park is significantly different than the “default” dog bark. Therefor, it could make sense for you to implement something as follows:

 public abstract class Dog { public virtual void Bark() { Console.WriteLine("Base Class implementation of Bark"); } } public class GoldenRetriever : Dog { // the Bark method is inherited from the Dog class } public class Poodle : Dog { // here we are overriding the base functionality of Bark with our new implementation // specific to the Poodle class public override void Bark() { Console.WriteLine("Poodle's implementation of Bark"); } } // Add a list of dogs to a collection and call the bark method. void Main() { var poodle = new Poodle(); var goldenRetriever = new GoldenRetriever(); var dogs = new List(); dogs.Add(poodle); dogs.Add(goldenRetriever); foreach (var dog in dogs) { dog.Bark(); } } // Output will be: // Poodle's implementation of Bark // Base Class implementation of Bark // 

As you can see, this would be a great way to keep your code DRY and allow for the base class implementation be called when any of the types can just rely on the default Bark instead of a special case implementation. The classs like GoldenRetriever, Boxer, Lab could all could inherit the “default” (bass class) Bark at no charge just because they implement the Dog abstract class.

But I’m sure you already knew that.

You are here because you want to understand why you might want to choose an interface over an abstract class or vice versa. Well one reason you may want to choose an interface over an abstract class is when you don’t have or want to prevent a default implementation. This is usually because the types that are implementing the interface not related in an “is a” relationship. Actually, they don’t have to be related at all except for the fact that each type “is able” or has “the ablity” to do something or have something.

Now what the heck does that mean? Well, for example: A human is not a duck…and a duck is not a human. Pretty obvious. However, both a duck and a human have “the ability” to swim (given that the human passed his swimming lessons in 1st grade 🙂 ). Also, since a duck is not a human or vice versa, this is not an “is a” realationship, but instead an “is able” relationship and we can use an interface to illustrate that:

 // Create ISwimable interface public interface ISwimable { public void Swim(); } // Have Human implement ISwimable Interface public class Human : ISwimable public void Swim() { //Human's implementation of Swim Console.WriteLine("I'm a human swimming!"); } // Have Duck implement ISwimable interface public class Duck: ISwimable { public void Swim() { // Duck's implementation of Swim Console.WriteLine("Quack! Quack! I'm a Duck swimming!") } } //Now they can both be used in places where you just need an object that has the ability "to swim" public void ShowHowYouSwim(ISwimable somethingThatCanSwim) { somethingThatCanSwim.Swim(); } public void Main() { var human = new Human(); var duck = new Duck(); var listOfThingsThatCanSwim = new List(); listOfThingsThatCanSwim.Add(duck); listOfThingsThatCanSwim.Add(human); foreach (var something in listOfThingsThatCanSwim) { ShowHowYouSwim(something); } } // So at runtime the correct implementation of something.Swim() will be called // Output: // Quack! Quack! I'm a Duck swimming! // I'm a human swimming! 

Using interfaces like the code above will allow you to pass an object into a method that “is able” to do something. The code doesn’t care how it does it…All it knows is that it can call the Swim method on that object and that object will know which behavior take at run-time based on its type.

Once again, this helps your code stay DRY so that you would not have to write multiple methods that are calling the object to preform the same core function (ShowHowHumanSwims(human), ShowHowDuckSwims(duck), etc.)

Using an interface here allows the calling methods to not have to worry about what type is which or how the behavior is implemented. It just knows that given the interface, each object will have to have implemented the Swim method so it is safe to call it in its own code and allow the behavior of the Swim method be handled within its own class.

Sommario:

So my main rule of thumb is use an abstract class when you want to implement a “default” functionality for a class hierarchy or/and the classs or types you are working with share a “is a” relationship (ex. poodle “is a” type of dog).

On the other hand use an interface when you do not have an “is a” relationship but have types that share “the ability” to do something or have something (ex. Duck “is not” a human. However, duck and human share “the ability” to swim).

Another difference to note between abstract classs and interfaces is that a class can implement one to many interfaces but a class can only inherit from ONE abstract class (or any class for that matter). Yes, you can nest classs and have an inheritance hierarchy (which many programs do and should have) but you cannot inherit two classs in one derived class definition (this rule applies to C#. In some other languages you are able to do this, usually only because of the lack of interfaces in these languages).

Also remember when using interfaces to adhere to the Interface Segregation Principle (ISP). ISP states that no client should be forced to depend on methods it does not use. For this reason interfaces should be focused on specific tasks and are usually very small (ex. IDisposable, IComparable ).

Another tip is if you are developing small, concise bits of functionality, use interfaces. If you are designing large functional units, use an abstract class.

Hope this clears things up for some people!

Also if you can think of any better examples or want to point something out, please do so in the comments below!

Previous comments about using abstract classs for common implementation is definitely on the mark. One benefit I haven’t seen mentioned yet is that the use of interfaces makes it much easier to implement mock objects for the purpose of unit testing. Defining IPet and PetBase as Jason Cohen described enables you to mock different data conditions easily, without the overhead of a physical database (until you decide it’s time to test the real thing).

Don’t use a base class unless you know what it means, and that it applies in this case. If it applies, use it, otherwise, use interfaces. But note the answer about small interfaces.

Public Inheritance is overused in OOD and expresses a lot more than most developers realize or are willing to live up to. See the Liskov Substitutablity Principle

In short, if A “is a” B then A requires no more than B and delivers no less than B, for every method it exposes.

Conceptually, an Interface is used to formally and semi-formally define a set of methods that an object will provide. Formally means a set of method names and signatures, semi-formally means human readable documentation associated with those methods. Interfaces are only descriptions of an API (after all, API stands for Application Programmer Interface ), they can’t contain any implementation, and it’s not possible to use or run an Interface. They only make explicit the contract of how you should interact with an object.

Classes provide an implementation, they can declare that they implement zero, one or more Interfaces. If a Class is intended to be inherited, the convention is to prefix the Class name with “Base”.

There is a distinction between a Base Class and an Abstract Base Classes (ABC). ABCs mix interface and implementation together. Abstract outside of computer programming means “summary”, that is “Abstract == Interface”. An Abstract Base Class can then describe both an interface, as well as an empty, partial or complete implementation that is intended to be inherited.

Opinions on when to use Interfaces versus Abstract Base Classes versus just Classes is going to vary wildly based on both what you are developing, and which language you are developing in. Interfaces are often associated only with statically typed languages such as Java or C#, but dynamically typed languages can also have Interfaces and Abstract Base Classes. In Python for example, the distinction is made clear between a Class, which declares that it implements an Interface, and an object, which is an instance of a Class, and is said to provide that Interface. It’s possible in a dynamic language that two objects that are both instances of the same Class, can declare that they provide completely different interfaces. In Python this is only possible for object attributes, while methods are shared state between all objects of a Class. However in Ruby, objects can have per-instance methods, so it’s possible that the Interface between two objects of the same Class can vary as much as the programmer desires (however, Ruby doesn’t have any explicit way of declaring Interfaces).

In dynamic languages the Interface to an object is often implicitly assumed, either by introspecting an object and asking it what methods it provides (Look Before You Leap) or preferably by simply attempting to use the desired Interface on an object and catching exceptions if the object doesn’t provide that Interface (Easier to Ask Forgiveness than Permission). This can lead to “false positives” where two Interfaces have the same method name but are semantically different, however the trade-off is that your code is more flexible since you don’t need to over specify up-front to anticipate all possible uses of your code.

Another option to keep in mind is using the “has-a” relationship, aka “is implemented in terms of” or “composition.” Sometimes this is a cleaner, more flexible way to structure things than using “is-a” inheritance.

It may not make as much sense logically to say that Dog and Cat both “have” a Pet, but it avoids common multiple inheritance pitfalls:

 public class Pet { void Bathe(); void Train(Trick t); } public class Dog { private Pet pet; public void Bathe() { pet.Bathe(); } public void Train(Trick t) { pet.Train(t); } } public class Cat { private Pet pet; public void Bathe() { pet.Bathe(); } public void Train(Trick t) { pet.Train(t); } } 

Yes, this example shows that there is a lot of code duplication and lack of elegance involved in doing things this way. But one should also appreciate that this helps to keep Dog and Cat decoupled from the Pet class (in that Dog and Cat do not have access to the private members of Pet), and it leaves room for Dog and Cat to inherit from something else–possibly the Mammal class.

Composition is preferable when no private access is required and you don’t need to refer to Dog and Cat using generic Pet references/pointers. Interfaces give you that generic reference capability and can help cut down on the verbosity of your code, but they can also obfuscate things when they are poorly organized. Inheritance is useful when you need private member access, and in using it you are committing yourself to highly coupling your Dog and Cat classs to your Pet class, which is a steep cost to pay.

Between inheritance, composition, and interfaces there is no one way that is always right, and it helps to consider how all three options can be used in harmony. Of the three, inheritance is typically the option that should be used the least often.

Prefer interfaces over abstract classs

Rationale, the main points to consider [two already mentioned here] are :

  • Interfaces are more flexible, because a class can implement multiple interfaces. Since Java does not have multiple inheritance, using abstract classs prevents your users from using any other class hierarchy. In general, prefer interfaces when there are no default implementations or state. Java collections offer good examples of this (Map, Set, etc.).
  • Abstract classs have the advantage of allowing better forward compatibility. Once clients use an interface, you cannot change it; if they use an abstract class, you can still add behavior without breaking existing code. If compatibility is a concern, consider using abstract classs.
  • Even if you do have default implementations or internal state, consider offering an interface and an abstract implementation of it . This will assist clients, but still allow them greater freedom if desired [1].
    Of course, the subject has been discussed at length elsewhere [2,3].

[1] It adds more code, of course, but if brevity is your primary concern, you probably should have avoided Java in the first place!

[2] Joshua Bloch, Effective Java, items 16-18.

[3] http://www.codeproject.com/KB/ar

It depends on your requirements. If IPet is simple enough, I would prefer to implement that. Otherwise, if PetBase implements a ton of functionality you don’t want to duplicate, then have at it.

The downside to implementing a base class is the requirement to override (or new ) existing methods. This makes them virtual methods which means you have to be careful about how you use the object instance.

Lastly, the single inheritance of .NET kills me. A naive example: Say you’re making a user control, so you inherit UserControl . But, now you’re locked out of also inheriting PetBase . This forces you to reorganize, such as to make a PetBase class member, instead.

@Joel: Some languages (eg, C++) allow multiple-inheritance.

I usually don’t implement either until I need one. I favor interfaces over abstract classs because that gives a little more flexibility. If there’s common behavior in some of the inheriting classs I move that up and make an abstract base class. I don’t see the need for both, since they essentially server the same purpose, and having both is a bad code smell (imho) that the solution has been over-engineered.

Regarding C#, in some senses interfaces and abstract classs can be interchangeable. However, the differences are: i) interfaces cannot implement code; ii) because of this, interfaces cannot call further up the stack to subclass; and iii) only can abstract class may be inherited on a class, whereas multiple interfaces may be implemented on a class.

I’ve found that a pattern of Interface > Abstract > Concrete works in the following use-case:

 1. You have a general interface (eg IPet) 2. You have a implementation that is less general (eg Mammal) 3. You have many concrete members (eg Cat, Dog, Ape) 

The abstract class defines default shared attributes of the concrete classs, yet enforces the interface. Per esempio:

 public interface IPet{ public boolean hasHair(); public boolean walksUprights(); public boolean hasNipples(); } 

Now, since all mammals have hair and nipples (AFAIK, I’m not a zoologist), we can roll this into the abstract base class

 public abstract class Mammal() implements IPet{ @override public walksUpright(){ throw new NotSupportedException("Walks Upright not implemented"); } @override public hasNipples(){return true} @override public hasHair(){return true} 

And then the concrete classs merely define that they walk upright.

 public class Ape extends Mammal(){ @override public walksUpright(return true) } public class Catextends Mammal(){ @override public walksUpright(return false) } 

This design is nice when there are lots of concrete classs, and you don’t want to maintain boilerplate just to program to an interface. If new methods were added to the interface, it would break all of the resulting classs, so you are still getting the advantages of the interface approach.

In this case, the abstract could just as well be concrete; however, the abstract designation helps to emphasize that this pattern is being employed.

An inheritor of a base class should have an “is a” relationship. Interface represents An “implements a” relationship. So only use a base class when your inheritors will maintain the is a relationship.

Use Interfaces to enforce a contract ACROSS families of unrelated classs. For example, you might have common access methods for classs that represent collections, but contain radically different data ie one class might represent a result set from a query, while the other might represent the images in a gallery. Also, you can implement multiple interfaces, thus allowing you to blend (and signify) the capabilities of the class.

Use Inheritance when the classs bear a common relationship and therefore have a similair structural and behavioural signature, ie Car, Motorbike, Truck and SUV are all types of road vehicle that might contain a number of wheels, a top speed