Menu
Coddy logo textTech

Interface vs Classe Abstraite

Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 26 sur 70.

Les interfaces et les classes abstraites vous permettent toutes deux de définir des contrats que d'autres classes doivent suivre, mais elles servent des objectifs différents et possèdent des capacités distinctes.

Une interface définit ce qu'une classe doit faire, sans aucune implémentation. C'est un contrat pur :

public interface IFlyable
{
    void Fly();
}

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

Une classe abstraite peut fournir à la fois un contrat et une implémentation partagée. C'est un plan partiel :

public abstract class Vehicle
{
    public string Brand { get; set; }
    
    public void StartEngine()
    {
        Console.WriteLine("Engine started");
    }
    
    public abstract void Drive();  // Doit être implémenté
}

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

Les principales différences se résument aux règles d'héritage et à l'objectif.

Une classe peut implémenter plusieurs interfaces mais ne peut hériter que d'une seule classe abstraite.

Utilisez une interface lorsque des classes non liées doivent partager un comportement (comme IFlyable pour les oiseaux et les avions). Utilisez une classe abstraite lorsque des classes liées partagent du code et un état communs (comme des véhicules partageant un mécanisme de démarrage du moteur).

Les classes abstraites peuvent avoir des constructeurs, des champs et des modificateurs d'accès sur les membres. Les interfaces ne le pouvaient pas traditionnellement, bien que le C# moderne autorise les implémentations par défaut.

En cas de doute, privilégiez les interfaces pour la flexibilité - vous pouvez toujours ajouter une classe abstraite plus tard si une implémentation partagée devient nécessaire.

challenge icon

Défi

Facile

Construisons un système de lecteur multimédia qui démontre quand utiliser des interfaces par rapport aux classes abstraites. Vous allez créer une conception où des appareils non liés partagent un comportement de lecture via une interface, tandis que des types de médias liés partagent une implémentation commune via une classe abstraite.

Vous organiserez votre code sur quatre fichiers :

  • IPlayable.cs : Définissez une interface appelée IPlayable dans l'espace de noms Media. Cette interface représente le contrat pour tout ce qui peut lire des médias - qu'il s'agisse d'un téléphone, d'un téléviseur ou d'un lecteur de musique dédié. Elle doit déclarer une seule méthode Play() qui retourne une chaîne de caractères (string).
  • MediaFile.cs : Définissez une classe abstraite appelée MediaFile dans l'espace de noms Media. Cela représente la base partagée pour tous les fichiers multimédias. Elle doit avoir une propriété Title (string) et une propriété Duration (int, représentant les secondes). Incluez un constructeur qui définit les deux valeurs. Ajoutez une méthode concrète appelée GetInfo() qui retourne "{Title} ({Duration}s)". Déclarez également une méthode abstraite GetType() qui retourne une chaîne de caractères - chaque type de média définira de quel type de fichier il s'agit.
  • AudioFile.cs : Définissez une classe AudioFile dans l'espace de noms Media qui hérite de MediaFile et implémente IPlayable. Ajoutez une propriété Artist (string). Le constructeur doit accepter le titre, la durée et l'artiste. Surchargez GetType() pour retourner "Audio". Implémentez Play() pour retourner "Playing audio: {Title} by {Artist}".
  • Program.cs : Dans votre fichier principal, créez un AudioFile en utilisant les valeurs d'entrée. Démontrez les deux aspects de la classe : appelez GetInfo() et GetType() (hérités de la classe abstraite), puis appelez Play() (de l'interface). Stockez le fichier audio dans une variable IPlayable et appelez à nouveau Play() pour montrer le polymorphisme d'interface.

Vous recevrez trois entrées :

  • Titre de la chanson
  • Durée en secondes
  • Nom de l'artiste

Affichez la sortie dans ce format :

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

Par exemple, si les entrées sont Bohemian Rhapsody, 354, et Queen, la sortie devrait être :

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

Remarquez comment AudioFile bénéficie des deux approches : il hérite de l'implémentation partagée (GetInfo()) de la classe abstraite tout en remplissant le contrat IPlayable. La classe abstraite permet la réutilisation du code pour les types de médias liés, tandis que l'interface permet à n'importe quelle classe non liée d'être "jouable" sans partager une hiérarchie d'héritage.

Aide-mémoire

Une interface définit un contrat que les classes doivent suivre, sans aucune implémentation :

public interface IFlyable
{
    void Fly();
}

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

Une classe abstraite fournit à la fois un contrat et une implémentation partagée :

public abstract class Vehicle
{
    public string Brand { get; set; }
    
    public void StartEngine()
    {
        Console.WriteLine("Engine started");
    }
    
    public abstract void Drive();  // Doit être implémenté
}

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

Différences clés :

  • Une classe peut implémenter plusieurs interfaces mais ne peut hériter que d'une seule classe abstraite
  • Utilisez des interfaces lorsque des classes non liées doivent partager un comportement
  • Utilisez des classes abstraites lorsque des classes liées partagent du code et un état communs
  • Les classes abstraites peuvent avoir des constructeurs, des champs et des modificateurs d'accès
  • Privilégiez les interfaces pour plus de flexibilité

Essayez vous-même

using System;
using Media;

class Program
{
    public static void Main(string[] args)
    {
        // Lire les valeurs d'entrée
        string title = Console.ReadLine();
        int duration = Convert.ToInt32(Console.ReadLine());
        string artist = Console.ReadLine();
        
        // TODO: Créer un AudioFile en utilisant les valeurs d'entrée
        
        // TODO: Afficher Info: suivi du résultat de GetInfo()
        
        // TODO: Afficher Type: suivi du résultat de GetType()
        
        // TODO: Afficher Direct: suivi du résultat de Play()
        
        // TODO: Stocker le fichier audio dans une variable IPlayable
        
        // TODO: Afficher Via Interface: suivi du résultat de Play() à partir de la variable IPlayable
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet