Menu
Coddy logo textTech

Explizite Interfaces

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 28 von 70.

Wenn eine Klasse mehrere Schnittstellen implementiert, die Member mit demselben Namen haben, tritt ein Namenskonflikt auf. Die explizite Schnittstellenimplementierung löst dies, indem sie es Ihnen ermöglicht, separate Implementierungen für jede Schnittstelle bereitzustellen.

Bei der expliziten Implementierung stellen Sie dem Membernamen den Schnittstellennamen voran und lassen den Zugriffsmodifizierer weg:

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");
    }
}

Explizit implementierte Member können nur über eine Variable des Schnittstellentyps aufgerufen werden, nicht über die Klasse selbst:

var adapter = new UniversalAdapter();
// adapter.Connect();  // Kompiliert nicht!

IAmericanPlug american = adapter;
american.Connect();  // Verbunden mit 120V

IEuropeanPlug european = adapter;
european.Connect();  // Verbunden mit 220V

Diese Technik ist auch nützlich, wenn du Schnittstellenmitglieder vor der öffentlichen API der Klasse verbergen möchtest. Wenn eine Methode nur sinnvoll ist, wenn das Objekt als eine bestimmte Schnittstelle behandelt wird, hält die explizite Implementierung die Oberfläche deiner Klasse sauber und erfüllt dennoch den Vertrag.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Berichtsgeneratorsystem, das veranschaulicht, wie die explizite Implementierung von Schnittstellen es einer einzelnen Klasse ermöglicht, je nach verwendeter Schnittstelle unterschiedliches Verhalten bereitzustellen. Du erstellst ein Dokument, das für die Anzeige anders formatiert werden kann als für den Druck.

Du organisierst deinen Code auf vier Dateien verteilt:

  • IDisplayable.cs: Definiere im Namespace IDisplayable eine Schnittstelle namens Reports. Diese Schnittstelle steht für Inhalte, die auf dem Bildschirm angezeigt werden können. Sie soll eine Methode Render() deklarieren, die einen String zurückgibt.
  • IPrintable.cs: Definiere im Namespace IPrintable eine Schnittstelle namens Reports. Diese Schnittstelle steht für Inhalte, die an einen Drucker gesendet werden können. Sie soll ebenfalls eine Methode Render() deklarieren, die einen String zurückgibt – beachte, dass dadurch ein Namenskonflikt mit IDisplayable entsteht!
  • Report.cs: Definiere im Namespace Report eine Klasse Reports, die sowohl IDisplayable als auch IPrintable implementiert. Der Bericht soll über eine Title-Eigenschaft (string) und eine Content-Eigenschaft (string) verfügen, wobei ein Konstruktor beide Werte festlegt. Verwende die explizite Implementierung von Schnittstellen, um unterschiedliches Verhalten für Render() bereitzustellen:
    • Bei der Anzeige: "[SCREEN] {Title}: {Content}"
    • Beim Drucken: "[PRINT] {Title} | {Content}"
  • Program.cs: Erstelle in deiner Hauptdatei mithilfe von Eingabewerten ein Report-Objekt. Da explizite Implementierungen nur über Schnittstellenvariablen aufgerufen werden können, speicherst du denselben Bericht sowohl in einer IDisplayable-Variable als auch in einer IPrintable-Variable und rufst anschließend für beide Render() auf, um zu zeigen, wie dasselbe Objekt je nach verwendeter Schnittstelle eine unterschiedliche Ausgabe erzeugt.

Du erhältst zwei Eingaben:

  • Berichtstitel
  • Berichtsinhalt

Gib die Ausgabe in diesem Format aus:

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

Wenn die Eingaben beispielsweise Sales Report und Q4 revenue increased by 15% lauten, sollte die Ausgabe wie folgt aussehen:

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

Beachte, wie sich dasselbe Report-Objekt je nach verwendeter Schnittstellenreferenz unterschiedlich verhält. Das ist die Stärke der expliziten Implementierung von Schnittstellen – sie löst Namenskonflikte und ermöglicht gleichzeitig kontextgerechtes Verhalten!

Probier es selbst

using System;
using Reports;

class Program
{
    public static void Main(string[] args)
    {
        // Eingabe lesen
        string title = Console.ReadLine();
        string content = Console.ReadLine();

        // TODO: Erstelle ein Report-Objekt mit dem Titel und Inhalt

        // TODO: Speichere den Bericht in einer IDisplayable-Variable

        // TODO: Speichere denselben Bericht in einer IPrintable-Variable

        // TODO: Gib die Anzeigeversion aus, indem Render() auf IDisplayable aufgerufen wird
        Console.WriteLine("Display version:");
        // Gib das Render-Ergebnis hier aus

        // TODO: Gib die Druckversion aus, indem Render() auf IPrintable aufgerufen wird
        Console.WriteLine("Print version:");
        // Gib das Render-Ergebnis hier aus
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C#-Compiler