Menu
Coddy logo textTech

Interfaces Explicites

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

Lorsqu’une classe implémente plusieurs interfaces qui possèdent des membres portant le même nom, vous êtes confronté à une collision de noms. L’implémentation explicite des interfaces résout ce problème en vous permettant de fournir des implémentations distinctes pour chaque interface.

Avec une implémentation explicite, vous préfixez le nom du membre avec le nom de l’interface et omettez le modificateur d’accès :

public interface IAmericanPlug
{
    void Connect();
}

public interface IEuropeanPlug
{
    void Connect();
}

public class UniversalAdapter : IAmericanPlug, IEuropeanPlug
{
    void IAmericanPlug.Connect()
    {
        Console.WriteLine("Connected to 120V");
    }
    
    void IEuropeanPlug.Connect()
    {
        Console.WriteLine("Connected to 220V");
    }
}

Les membres implémentés explicitement sont accessibles uniquement via une variable du type de l’interface, et non via la classe elle-même :

var adapter = new UniversalAdapter();
// adapter.Connect();  // Ne compilera pas !

IAmericanPlug american = adapter;
american.Connect();  // Connecté au 120V

IEuropeanPlug european = adapter;
european.Connect();  // Connecté au 220V

Cette technique est également utile lorsque vous souhaitez masquer des membres d’interface de l’API publique de la classe. Si une méthode n’a de sens que lorsque l’objet est considéré comme une interface spécifique, l’implémentation explicite permet de garder la surface de votre classe propre tout en respectant le contrat.

challenge icon

Défi

Facile

Construisons un système de génération de rapports qui montre comment l’implémentation explicite d’interfaces permet à une seule classe de fournir des comportements différents selon l’interface utilisée. Vous allez créer un document qui peut être formaté différemment pour l’affichage et pour l’impression.

Vous organiserez votre code sur quatre fichiers :

  • IDisplayable.cs : définissez une interface appelée IDisplayable dans l’espace de noms Reports. Cette interface représente du contenu pouvant être affiché à l’écran. Elle doit déclarer une méthode Render() qui renvoie une chaîne de caractères.
  • IPrintable.cs : définissez une interface appelée IPrintable dans l’espace de noms Reports. Cette interface représente du contenu pouvant être envoyé à une imprimante. Elle doit également déclarer une méthode Render() qui renvoie une chaîne de caractères — remarquez que cela crée une collision de noms avec IDisplayable !
  • Report.cs : définissez une classe Report dans l’espace de noms Reports qui implémente à la fois IDisplayable et IPrintable. Le rapport doit posséder une propriété Title (chaîne de caractères) et une propriété Content (chaîne de caractères), ainsi qu’un constructeur qui définit les deux valeurs. Utilisez l’implémentation explicite d’interface pour fournir des comportements Render() différents :
    • Lors du rendu pour l’affichage : "[SCREEN] {Title}: {Content}"
    • Lors du rendu pour l’impression : "[PRINT] {Title} | {Content}"
  • Program.cs : dans votre fichier principal, créez un Report à l’aide des valeurs saisies. Comme les implémentations explicites ne sont accessibles que par l’intermédiaire de variables d’interface, stockez le même rapport dans une variable IDisplayable et dans une variable IPrintable, puis appelez Render() sur chacune afin de montrer comment le même objet produit une sortie différente selon l’interface que vous utilisez.

Vous recevrez deux entrées :

  • Titre du rapport
  • Contenu du rapport

Affichez la sortie dans ce format :

Display version:
{Render() via IDisplayable}
Print version:
{Render() via IPrintable}

Par exemple, si les entrées sont Sales Report et Q4 revenue increased by 15%, la sortie doit être :

Display version:
[SCREEN] Sales Report: Q4 revenue increased by 15%
Print version:
[PRINT] Sales Report | Q4 revenue increased by 15%

Remarquez comment le même objet Report se comporte différemment selon la référence d’interface que vous utilisez pour y accéder. C’est toute la puissance de l’implémentation explicite d’interface : résoudre les collisions de noms tout en fournissant un comportement adapté au contexte !

Essayez vous-même

using System;
using Reports;

class Program
{
    public static void Main(string[] args)
    {
        // Lire l'entrée
        string title = Console.ReadLine();
        string content = Console.ReadLine();

        // TODO: Créer un objet Report avec le titre et le contenu

        // TODO: Stocker le rapport dans une variable IDisplayable

        // TODO: Stocker le même rapport dans une variable IPrintable

        // TODO: Afficher la version d'affichage en appelant Render() sur IDisplayable
        Console.WriteLine("Display version:");
        // Afficher le résultat du rendu ici

        // TODO: Afficher la version d'impression en appelant Render() sur IPrintable
        Console.WriteLine("Print version:");
        // Afficher le résultat du rendu ici
    }
}
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

Entraînez-vous par vous-même : Compilateur C# en ligne