Menu
CoddyTech

Interfaccia o classe astratta

Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 26 di 70.

Sia le interfacce sia le classi astratte ti consentono di definire contratti che le altre classi devono rispettare, ma hanno scopi diversi e capacità distinte.

Un’interfaccia definisce cosa deve fare una classe, senza alcuna implementazione. È un contratto puro:

public interface IFlyable
{
    void Fly();
}

public class Bird : IFlyable
{
    public void Fly()
    {
        Console.WriteLine("Flapping wings");
    }
}

Una classe astratta può fornire sia un contratto sia un’implementazione condivisa. È un modello parziale:

public abstract class Vehicle
{
    public string Brand { get; set; }
    
    public void StartEngine()
    {
        Console.WriteLine("Engine started");
    }
    
    public abstract void Drive();  // Deve essere implementato
}

public class Car : Vehicle
{
    public override void Drive()
    {
        Console.WriteLine("Driving on roads");
    }
}

Le differenze principali riguardano le regole di ereditarietà e lo scopo.

Una classe può implementare più interfacce, ma ereditare da una sola classe astratta.

Una classe può anche ereditare da una classe astratta e implementare interfacce contemporaneamente: dopo i due punti viene prima la classe base, poi le interfacce, separate da virgole:

public class Airplane : Vehicle, IFlyable
{
    public override void Drive()
    {
        Console.WriteLine("Taxiing to the runway");
    }

    public void Fly()
    {
        Console.WriteLine("Flying above the clouds");
    }
}

Usa un'interfaccia quando classi non correlate devono condividere un comportamento (come IFlyable per uccelli e aeroplani). Usa una classe astratta quando classi correlate condividono codice e stato comuni (come i veicoli che condividono un meccanismo di avviamento del motore).

Le classi astratte possono avere costruttori, campi e modificatori di accesso sui membri. Tradizionalmente, le interfacce non potevano averli, anche se le versioni moderne di C# consentono implementazioni predefinite.

In caso di dubbio, preferisci le interfacce per una maggiore flessibilità: puoi sempre aggiungere una classe astratta in seguito, se diventa necessaria un'implementazione condivisa.

challenge icon

Sfida

Facile

Costruiamo un sistema di riproduzione multimediale che mostri quando usare le interfacce rispetto alle classi astratte. Creerai un progetto in cui dispositivi non correlati condividono il comportamento di riproduzione tramite un'interfaccia, mentre tipi di contenuti multimediali correlati condividono un'implementazione comune tramite una classe astratta.

Organizzerai il codice in quattro file:

  • IPlayable.cs: definisci un'interfaccia chiamata IPlayable nello spazio dei nomi Media. Questa interfaccia rappresenta il contratto per qualsiasi elemento in grado di riprodurre contenuti multimediali, che si tratti di un telefono, di una TV o di un lettore musicale dedicato. Dovrebbe dichiarare un unico metodo Play() che restituisce una stringa.
  • MediaFile.cs: definisci una classe astratta chiamata MediaFile nello spazio dei nomi Media. Rappresenta la base condivisa per tutti i file multimediali. Dovrebbe avere una proprietà Title (stringa) e una proprietà Duration (int, che rappresenta i secondi). Includi un costruttore che imposta entrambi i valori. Aggiungi un metodo concreto chiamato GetInfo() che restituisce "{Title} ({Duration}s)". Dichiara anche un metodo astratto GetType() che restituisce una stringa: ogni tipo di contenuto multimediale definirà che tipo di file è.
  • AudioFile.cs: definisci una classe AudioFile nello spazio dei nomi Media che eredita da MediaFile e implementa IPlayable. Aggiungi una proprietà Artist (stringa). Il costruttore dovrebbe accettare titolo, durata e artista. Esegui l'override di GetType() affinché restituisca "Audio". Implementa Play() affinché restituisca "Playing audio: {Title} by {Artist}".
  • Program.cs: nel file principale, crea un AudioFile usando i valori di input. Mostra entrambi gli aspetti della classe: chiama GetInfo() e GetType() (ereditati dalla classe astratta), poi chiama Play() (dall'interfaccia). Memorizza il file audio in una variabile IPlayable e chiama di nuovo Play() per mostrare il polimorfismo dell'interfaccia.

Riceverai tre input:

  • Titolo della canzone
  • Durata in secondi
  • Nome dell'artista

Stampa l'output in questo formato:

Info: {GetInfo() result}
Type: {GetType() result}
Direct: {Play() result}
Via Interface: {Play() result from IPlayable variable}

Per esempio, se gli input sono Bohemian Rhapsody, 354 e Queen, l'output dovrebbe essere:

Info: Bohemian Rhapsody (354s)
Type: Audio
Direct: Playing audio: Bohemian Rhapsody by Queen
Via Interface: Playing audio: Bohemian Rhapsody by Queen

Nota come AudioFile tragga vantaggio da entrambi gli approcci: eredita l'implementazione condivisa (GetInfo()) dalla classe astratta e al tempo stesso rispetta il contratto IPlayable. La classe astratta consente di riutilizzare il codice per tipi di contenuti multimediali correlati, mentre l'interfaccia permette a qualsiasi classe non correlata di essere "riproducibile" senza condividere una gerarchia di ereditarietà.

Provalo tu

using System;
using Media;

class Program
{
    public static void Main(string[] args)
    {
        // Leggi i valori di input
        string title = Console.ReadLine();
        int duration = Convert.ToInt32(Console.ReadLine());
        string artist = Console.ReadLine();
        
        // TODO: Crea un AudioFile usando i valori di input
        
        // TODO: Stampa Info: seguito dal risultato di GetInfo()
        
        // TODO: Stampa Type: seguito dal risultato di GetType()
        
        // TODO: Stampa Direct: seguito dal risultato di Play()
        
        // TODO: Memorizza il file audio in una variabile IPlayable
        
        // TODO: Stampa Via Interface: seguito dal risultato di Play() ottenuto dalla variabile IPlayable
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C# online