Quando usare una classe astratta e un'interfaccia in C #

Quando si progettano applicazioni, è importante sapere quando utilizzare una classe astratta e quando utilizzare un'interfaccia. Sebbene le classi e le interfacce astratte sembrino simili in qualche modo, ci sono differenze chiave che determineranno quale sia la scelta migliore per ciò che stai cercando di realizzare. In questo post del blog discuterò di queste differenze e di come decidere quando usarle.

La risposta breve: una classe astratta consente di creare funzionalità che le sottoclassi possono implementare o sovrascrivere. Un'interfaccia consente solo di definire la funzionalità, non di implementarla. E mentre una classe può estendere solo una classe astratta, può trarre vantaggio da più interfacce. 

Spiegazione della classe astratta C #

Una classe astratta è un tipo speciale di classe che non può essere istanziato. Una classe astratta è progettata per essere ereditata da sottoclassi che implementano o sovrascrivono i suoi metodi. In altre parole, le classi astratte sono o parzialmente implementate o non implementate affatto. Puoi avere funzionalità nella tua classe astratta: i metodi in una classe astratta possono essere sia astratti che concreti. Una classe astratta può avere costruttori: questa è una delle principali differenze tra una classe astratta e un'interfaccia. È possibile sfruttare le classi astratte per progettare componenti e specificare un certo livello di funzionalità comune che deve essere implementato dalle classi derivate.

Spiegazione dell'interfaccia C #

Un'interfaccia è fondamentalmente un contratto, non ha alcuna implementazione. Un'interfaccia può contenere solo dichiarazioni di metodo; non può contenere definizioni di metodi. Né puoi avere dati dei membri in un'interfaccia. Mentre una classe astratta può contenere definizioni di metodi, campi e costruttori, un'interfaccia può avere solo dichiarazioni di eventi, metodi e proprietà. I metodi dichiarati in un'interfaccia devono essere implementati dalle classi che implementano l'interfaccia. Notare che una classe può implementare più di un'interfaccia ma estendere solo una classe. La classe che implementa l'interfaccia dovrebbe implementare tutti i suoi membri. Come una classe astratta, non è possibile creare un'istanza di un'interfaccia.

Devo usare una classe astratta o un'interfaccia?

Le classi astratte forniscono la flessibilità di disporre di alcuni metodi concreti e di altri metodi che le classi derivate dovrebbero implementare. Al contrario, se usi le interfacce, dovresti implementare tutti i metodi nella classe che estende l'interfaccia. Una classe astratta è una buona scelta se hai piani per un'espansione futura, cioè se è probabile un'espansione futura nella gerarchia delle classi. Se desideri fornire supporto per l'espansione futura quando utilizzi le interfacce, dovrai estendere l'interfaccia e crearne una nuova.

In una nota diversa, è facile aggiungere una nuova interfaccia alla gerarchia, se necessario. Tuttavia, se si dispone già di una classe astratta nella gerarchia, non è possibile aggiungerne un'altra, ovvero è possibile aggiungere una classe astratta solo se nessuna è disponibile. Dovresti utilizzare un'interfaccia se desideri un contratto su alcuni comportamenti o funzionalità. Non utilizzare un'interfaccia se è necessario scrivere lo stesso codice per i metodi dell'interfaccia. In questo caso, dovresti usare una classe astratta, definire il metodo una volta e riutilizzarlo secondo necessità. Usa le interfacce per separare il codice dell'applicazione da implementazioni specifiche di esso o per limitare l'accesso ai membri di un certo tipo.

Come afferma la documentazione delle interfacce di Microsoft:

Utilizzando le interfacce, è possibile, ad esempio, includere comportamenti da più origini in una classe. Questa funzionalità è importante in C # perché il linguaggio non supporta l'ereditarietà multipla delle classi. Inoltre, è necessario utilizzare un'interfaccia se si desidera simulare l'ereditarietà per le strutture, poiché non possono effettivamente ereditare da un'altra struttura o classe.

Implementazioni implicite ed esplicite dell'interfaccia

Le interfacce possono essere implementate implicitamente o esplicitamente. Lasciatemi spiegare come differiscono queste due implementazioni. Considera un'interfaccia chiamata IBusinessLogic.

interfaccia pubblica IBusinessLogic

{

   void Initialize ();

}

La seguente classe denominata BusinessLogicimplementa l' IBusinessLogicinterfaccia.

classe pubblica BusinessLogic: IBusinessLogic

{

   public void Initialize ()

   {

       // Un po 'di codice

   }

}

È possibile creare un'istanza della BusinessLogicclasse in modo esplicito e quindi chiamare il Initialize()metodo come mostrato di seguito.

 IBusinessLogic businessLogic = new BusinessLogic ();

businessLogic.Initialize ();

Il frammento di codice seguente illustra come implementare l' IBusinessLogicinterfaccia in modo implicito.

classe pubblica BusinessLogic: IBusinessLogic

{

   void IBusinessLogic.Initialize ()

   {

   }

}

È ora possibile richiamare il Initialize()metodo allo stesso modo utilizzando un riferimento IBusinessLogicall'interfaccia. La differenza nei due approcci è che quando si implementa l'interfaccia esplicitamente nella propria classe, si è costretti a richiamare un metodo della propria interfaccia utilizzando solo un riferimento all'interfaccia. Pertanto il seguente frammento di codice non funzionerebbe, ovvero non verrà compilato.

 BusinessLogic businessLogic = nuovo BusinessLogic ();

businessLogic.Initialize ();

Come fare di più in C #:

  • Quando usare una classe astratta e un'interfaccia in C #
  • Come lavorare con AutoMapper in C #
  • Come usare le espressioni lambda in C #
  • Come lavorare con i delegati Action, Func e Predicate in C #
  • Come lavorare con i delegati in C #
  • Come implementare un semplice logger in C #
  • Come lavorare con gli attributi in C #
  • Come lavorare con log4net in C #
  • Come implementare il modello di progettazione del repository in C #
  • Come lavorare con la riflessione in C #
  • Come lavorare con Filesystemwatcher in C #
  • Come eseguire l'inizializzazione pigra in C #
  • Come lavorare con MSMQ in C #
  • Come lavorare con i metodi di estensione in C #
  • Come utilizzare espressioni lambda in C #
  • Quando usare la parola chiave volatile in C #
  • Come utilizzare la parola chiave yield in C #
  • Come implementare il polimorfismo in C #
  • Come creare il proprio pianificatore di attività in C #
  • Come lavorare con RabbitMQ in C #
  • Come lavorare con una tupla in C #
  • Esplorazione di metodi virtuali e astratti in C #