Log in

Differenze tra classi astratte ed interfacce

di: Giorgio Borelli - del: 08 February 2010
Filed Under: C#

quali sono le caratteristiche e le principali differenze tra le classi astratte e le interfacce nella programmazione orientata agli oggettiLe classi astratte e le interfacce sono due concetti fondamentali della programmazione orientata agli oggetti (OOP, Object Oriented Programming), a prescindere dal linguaggio usato, sia questo Java, C++ o C#. L'importanza di conoscere i concetti teorici che stanno alla base di questi due elementi, è fondamentale per un buon programmatore; capire la differenza tra classi astratte ed interfacce permette di valutare in modo corretto quando usare l'una e quando usare l'altra.

 

Sia le classi astratte che le interfacce non possono essere instanziate poichè al loro interno definiscono soltanto i metodi e le proprietà che dovranno essere implementate dalle classi che deriveranno da esse, rappresentano pertanto un modello, oserei dire un "template" per le classi che una volta derivate da esse ed instanziate ne implementeranno il comportamento.

 

Classi astratte ed interfacce, così simili tra loro, possono confondere le idee ai neo programmatori che per le prime volte si avvicinano a questi concetti ed al polimorfismo della OOP, ma sebbene le similitudini sono molte vi sono delle sottili ma fondamentali differenze concettuali che è bene avere chiare in mente, per capire quando usare una classe astratta e quando una interfaccia.

 

 

Passiamo a descrivere brevemente prima le classi astratte e poi le interfacce, dopodichè ne evidenzieremo le differenze concettuali e di programmazione. Sebbene questi concetti teorici esulano dal linguaggio ae oggetti usato, come sintassi per i nostri esempi faremo riferimento al linguaggio C#, che è quello che ci piace di più ;)

 

Le Classi Astratte

Una classe astratta è una classe che non può essere instanziata e che serve solo per essere derivata, definendo al suo interno metodi e proprietà tutti o in parte anch'essi astratti. Una classe astratta che implementa solo ed esclusivamente metodi e proprietà astratte viene detta classe astratta pura.

Per definire una classe astratta in C#, dobbiamo anteporre alla definizione della classe la keyword abstract, stessa cosa vale per la definizione di metodi e proprietà astratte, come possiamo vedere nell'esempio seguente:

 

public abstract class Mammifero {

//metodo astratto

public abstract GetModoCamminare();

 

 

//proprietà astratta

public abstract string Name { get; set; }

...

}

 

Le classi astratte permetto d'implementare il concetto di polimorfismo, uno dei capisaldi della programmazione orientata agli ogetti. Il polimorfismo consente di assegnare comportamenti differenti a instanze di classi differenti devivanti tutte dalla stessa classe base, in questo caso la classe astratta. Per implementare il polimorfismo però i metodi e le proprietà del tipo base devono essere dichiarati come astratti o virtuali, affinchè questi possano essere riscritti (override) dal tipo derivato che ne instanzierà un particolare oggetto differente da un'altro ma con caratteristiche simili poichè derivanti entrambi dalla stessa classe madre, che ne definisce i comportamenti comuni tramite le signature dei metodi astratti.

Nel nostro esempio abbiamo definito una classe astratta Mammifero con un metodo modo di camminare ed una proprietà per il nome, le possibili instanze potrebbero essere:

 

public class Uomo: Mammifero {

//metodo astratto

public override string GetModoCamminare();

 

 

//proprietà astratta

public override string Name { get; set; }

...

}

 

Come notate, la classe uomo deriva da quella mammifero (classe astratta) e ne implementa i metodi e le proprietà astratte tramite override, per spiegare il concetto facciamo un banale esempio, la classe astratta definisce (ma non implementa) il metodo modo di camminare, nell'istanza della classe uomo questo metodo ritornerà bipede, mentre per un'istanza cane tornerebbe quadrupede, vedete il polimorfismo, a concetti comuni s'implementano comportamenti differenti.

 

Nota:  è bene precisare che tra metodi astratti e virtuali vi è una sostanziale differenza, i primi vengono solamente definiti nella classe astratta ed ognuno di esso deve essere necessariamente implementato nella classe derivata, i metodi virtuali possono invece essere anche implementati nella classe astratta e se questi non vengono riscritti (override) nella classe derivata, questa implementerà il metodo (virtuale) della classe astratta. Si definisce un metodo virtuale in C#, mettendo la keyword virtual prima della definizione del metodo stesso.

 

Le Interfacce

Le interfacce sono molto simili alle classi astratte, in quanto anch'essa definisce metodi e proprietà astratte. Nelle interfacce non troveremo l'implemetazione di alcun metodo o proprietà, come per le classi astratte pure, si dice che le interfacce stipulino un contratto con la classe derivata che le implementa.

 

Per definire un'interfaccia in C#, bisogna anteporre la keyword interface al nome dell'interfaccia stessa, inoltre gli access modifier per i membri non vengono specificati nelle interfacce. Proviamo ad es. a definire un'interfaccia che definisca un metodo che sarà comune a tutte le sue classi derivate:

 

public interface ICalc {

//metodo dell'interfaccia

public Count();

 

 ...

}

 

In questo semplicissimo esempio abbiamo definito un solo metodo per l'interfaccia, ma queste possono definire non solo metodi, ma anche proprietà ed eventi.

 

Solitamente i nomi delle interfacce vengono preceduti da una i maiuscola proprio per identificarle immediatamente all'interno del codice e distinguerle dalle classi, per quanto riguarda la loro implementazione invece, questa è identica alle regole usate per l'ereditarietà tra le classi, quindi basta postporre i due punti ":" al nome della classe e scrivere di seguito il nome dell'interfaccia che si vuole implementare. Una prima differenza tra classi astratte ed interfacce, almeno in C# e Visual Basic, e che mentre per le classi non è ammessa l'ereditarietà multipla, ma soltanto quella singola, questo non è vero per le interfacce. Una classe derivata può implemetare più di una interfaccia contemporaneamente, basterà separare con una virgola i nomi delle interfacce che si vogliono implementare per quella classe. Ovviamente una classe può derivare contemporaneamente da una classe madre e da una o più interfacce basta separare i nomi dell'une e delle altre sempre con le virgole.

 

A differenza delle classi astratte per l'implementazione di una interfaccia non si rende necessario usare la keyword override, basterà implementare il metodo definito nella interfaccia.

 

Quando usare le classi astratte e quando le Interfacce

Come abbiamo visto, sia le classi astratte che le interfacce rappresentano un modello, un contratto che la classe derivata deve rispettare implementando i metodi e le proprietà definite nel tipo base, ma allora al di là delle piccole differenze di sintassi qual'è la sostanziale differenza tra classi astratte pure ed interfacce, come capire quando usare l'una e quando le altre?  La risposta migliore è a seconda del tipo di contratto che la classe derivata deve implementare col tipo base, le classi astratte pure definiscono un legame più forte con la classe derivata poichè ne rappresentano il tipo base definendone il comportamento comune (vedi l'es. della classe mammifero). Mentre le interfacce possono essere usate per definire un modello generico, che implementa un comportamento comune a classi di vario genere e natura, ad esempio il metodo calc dell'iiterfaccia ICalc potrebbe essere comune sia ad un'istanza di una classe calcolatrice che a quello di un'istanza punto geometrico.

 

Se mi permettete una definizione personale, direi che le classi astratte pure definiscono un contratto di tipo verticale (dedicato) con le instanze delle classi figlie, mentre le interfacce rappresentano di più un contratto di tipo orizzontale (generico) con gli oggetti che le implementeranno.

 

 

Se volete seguire i post di www.informaticando.net iscrivetevi al suo feed RSS





Comments (8) -

8/31/2011 5:51:24 PM #

Cosimo Meli

Questo articolo mi è piaciuto davvero molto, ben fatto!
Per creare una classe che non deve poter essere istanziata, ovvero una collezione di metodi e costanti statici, in Java cosa conviene? Pensavo a una classe astratta statica, ma non so se effettivamente è la scelta più corretta dal punto di vista teorico.

Cosimo Meli | Reply

8/31/2011 7:52:24 PM #

Giorgio Borelli

Ciao Cosimo, grazie per il complimento sull'articolo, come sei magnanimo vuoi dire che gli altri non ti sono piaciuti tanto?

Per poter creare una classe che non può essere istanziata devi creare una Classe Statica, punto, un solo riferimento in memoria (la classe statica) condiviso nel suo scope di visibilità, la quale accede ai suoi metodi e proprietà statiche attraverso l'operatore punto; non crei l'oggetto, non usi il costruttore, la invochi così per com'è.

Non confondere Classi Astratte con Classi Statiche, vero è che non istanzi nemmeno la Classe Astratta, ma questa serve per definire un modello che sarà istanziato e personalizzato nelle classi figlie, mentre la Classe Statica la usi e come, addirittura la invochi direttamente, invece la Classe Astratta se non la fai ereditare non ti serve a nulla.

Per Capire quale tipo di Classe usare, bisogna fare un'analisi attenta dell'astrazione della realtà che intendi rappresentare, e fare le scelte più giuste per un'implementazione elegante, funzionale ed ottimizzata del codice OOP del tuo progetto.
Non centra il linguaggio che usi, Java, C# o chichessia, anche se puoi farlo, io difficilmente mischierei Classe Astratte con metodi statici, mai visto niente del genere. Mi viene da pensare che l'analisi del problema è stata fatta in modo errato e probabilmente esiste una soluzione più semplice.

La classe statica solitamente si usa per gestire degli aspetti comuni a tutto il software (o applicazione web), tipo impostazioni di configurazione, recuperare nome della connection string e simili, non la usi per astrarre la realta come invece fai con le Classi normali, la derivazione e gli altri aspetti della programmazione orientata agli ogetti.

Spero di essere stato chiaro, se hai ulteriori domande io sono qua, ciauz!

Giorgio Borelli | Reply

8/31/2011 9:58:15 PM #

davide

Buon articolo breve e chiaro.
Continuando sull'astrazione come costruire dipendenze  e quando inniettarle con i webform.

davide | Reply

8/31/2011 10:52:42 PM #

Giorgio Borelli

Ciao Davide, e grazie per il tuo intervento e per il complimento.

Tuttavia, non riesco a comprendere la tua domanda, puoi articolarla in maniera diversa, non riesco a coglierne il senso, grazie.

Giorgio Borelli | Reply

9/27/2011 5:33:26 PM #

Carlo

Dopo aver letto l'articolo ho le idee ancora più confuse di prima :-(

Carlo | Reply

9/27/2011 10:37:36 PM #

Giorgio Borelli

"Fuso e Confuso" come cantava Lelluccio, o ancora "Tu resta pure ma io vado via" come disse il cervello di Homer ad Homer.

Certi concetti, più astratti e teorici, possono risultare ostici e difficili da fare propri, in questi casi la messa in pratica può aiutare molto, permette di entrare nei meccanismi e negli ingranaggi della programmazione molto di più di quanto non faccia un articolo o delle pagine scritte.

Carlo prova con degli esempi, se vuoi invece chiedere qualcosa posta pure la tua domanda, vediamo se riusciamo ad esserti d'aiuto più di quanto non lo sia stato l'articolo, che ritengo comunque chiaro semplice avendo un minimo di basi di OOP.

Giorgio Borelli | Reply

10/3/2011 7:01:39 PM #

fabioraciti

Concordo pienamente sulla tua ultima definizione finale per descrivere le differenze tra classe astratta pura e interfaccia della classe

fabioraciti | Reply

10/3/2011 7:53:00 PM #

Giorgio Borelli

Grazie Fabio, la tua approvazione alla mia personale definizione di  classi astratte ed interfacce avvalora il fatto che essa riassume e rende bene l'idea delle loro differenze.

Se vuoi aggiungere dell'altro su Classi Astratte ed Interfacce, saremo lieti di leggerti.

Giorgio Borelli | Reply

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

Tag cloud

RecentComments

Comment RSS

Month List

Most comments

Claudio Claudio
5 comments
it Italy
Jenny Jenny
4 comments
Raven Raven
3 comments
Cosimo Meli Cosimo Meli
3 comments
umberto umberto
3 comments
it Italy
Giorgio Giorgio
3 comments
it Italy
Giuseppe Giuseppe
3 comments
Mikele Mikele
3 comments
it Italy
andrea andrea
2 comments
it Italy
gio gio
2 comments
it Italy