Le classi e le interfacce sono due concetti fondamentali della programmazione orientata agli oggetti (OOP, Object Oriented Programming), a prescindere dal linguaggio usato.

Classi e Interfacce, definiscono metodi e proprietà e non possono essere istanziate.

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.

Le Classi Astratte

Una classe astratta è una classe che non può essere istanziata 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.

Le classi astratte permetto d’implementare il concetto di polimorfismo, uno dei capisaldi della programmazione orientata agli oggetti.

Il polimorfismo

Il polimorfismo consente di assegnare comportamenti differenti a istanze di classi differenti derivanti 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 istanzierà 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.

Le Interfacce

Le interfacce sono molto simili alle classi astratte, in quanto anch’essa definisce metodi e proprietà astratte. Nelle interfacce non troveremo l’implementazione 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.

Solitamente i nomi delle interfacce vengono preceduti da una i maiuscola proprio per identificarle immediatamente all’interno del codice e distinguerle dalle classi.

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.