Zum Fußzeileninhalt springen
Iron Academy Logo
Lernen Sie C#
Lernen Sie C#

Andere Kategorien

Abstrakte C#-Klassen verstehen

Tim Corey
19m 59s

Abstrakte Klassen in C# sind ein grundlegendes Konzept, das bei Entwicklern oft Fragen aufwirft. In seinem Video "C# Abstract Classes - What They Are, How to Use Them, and Best Practices" geht Tim Corey darauf ein, was abstrakte Klassen sind, wie man sie verwendet und was die besten Methoden sind. Dieser Artikel fasst die wichtigsten Punkte aus seinem Video zusammen und verwendet Zeitangaben als Referenz.

Einführung

Tim (0:00) erklärt, dass abstrakte Klassen oft in Bezug auf ihren Zweck, ihre Funktionalität und ihre Bedeutung in Frage gestellt werden. Er beschreibt eine abstrakte Klasse als eine Mischung aus einer vollständigen Basisklasse und einer Schnittstelle, die in Bezug auf die Funktionalität zwischen diesen beiden liegt.

Demo Anwendung Walk-through

Bei (0:59) geht Tim durch eine Demo-Anwendung, um abstrakte Klassen zu demonstrieren. Die Anwendung besteht aus einer Konsolenanwendung und einer Klassenbibliothek mit zwei Datenzugriffsklassen, die Datenbankoperationen simulieren. Diese Klassen verfügen über Methoden zum Laden und Speichern von Daten, anhand derer Tim die Gemeinsamkeiten und Unterschiede zwischen abstrakten Klassen, Basisklassen und Schnittstellen veranschaulicht.

Hier ist der ursprüngliche Code für die Basisklasse und die abgeleiteten Klassen:

// Base Class Definition
public class DataAccess
{
    // Method to load the connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Method to load data
    public void LoadData()
    {
        Console.WriteLine("Loading data...");
    }

    // Method to save data
    public void SaveData()
    {
        Console.WriteLine("Saving data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQL data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Overriding SaveData method to specify SQL data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLiteDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQLite data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQLite data...");
    }

    // Overriding SaveData method to specify SQLite data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQLite data...");
    }
}
// Base Class Definition
public class DataAccess
{
    // Method to load the connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Method to load data
    public void LoadData()
    {
        Console.WriteLine("Loading data...");
    }

    // Method to save data
    public void SaveData()
    {
        Console.WriteLine("Saving data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQL data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Overriding SaveData method to specify SQL data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}

// Derived class that inherits from DataAccess
public class SQLiteDataAccess : DataAccess
{
    // Overriding LoadData method to specify SQLite data loading
    public new void LoadData()
    {
        Console.WriteLine("Loading SQLite data...");
    }

    // Overriding SaveData method to specify SQLite data saving
    public new void SaveData()
    {
        Console.WriteLine("Saving SQLite data...");
    }
}

Erstellen einer Basisklasse

Tim erklärt bei (3:21), wie man eine Basisklasse erstellt. Er refaktoriert den Code, um allgemeine Methoden wie LoadConnectionString in eine Basisklasse namens DataAccess zu verschieben. Durch die Vererbung von dieser Basisklasse erhalten andere Klassen wie SQLDataAccess und SQLiteDataAccess Zugriff auf diese gemeinsamen Methoden, wodurch Code-Duplikationen reduziert werden.

Die Basisklasse abstrakt machen

Bei (5:56) wandelt Tim die Basisklasse in eine abstrakte Klasse um, um die Unterschiede zu verdeutlichen. Er ändert DataAccess in eine abstrakte Klasse, um zu verhindern, dass sie direkt instanziiert wird. Stattdessen können nur Klassen, die von dieser abstrakten Klasse erben, wie SQLiteDataAccess und SQLDataAccess, ihre Methoden implementieren und ihre gemeinsame Funktionalität nutzen.

So ändert sich der Code, wenn DataAccess eine abstrakte Klasse wird:

// Abstract Base Class Definition
public abstract class AbstractDataAccess
{
    // Shared method to load connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Abstract methods that must be implemented by derived classes
    public abstract void LoadData();
    public abstract void SaveData();
}
// Abstract Base Class Definition
public abstract class AbstractDataAccess
{
    // Shared method to load connection string
    public string LoadConnectionString()
    {
        Console.WriteLine("Loading the connection string...");
        return "Test Connection String";
    }

    // Abstract methods that must be implemented by derived classes
    public abstract void LoadData();
    public abstract void SaveData();
}

Interface-Teil in der abstrakten Klasse

Tim erklärt bei (8:34), wie abstrakte Klassen die Eigenschaften von Schnittstellen und Basisklassen vereinen. Er deklariert abstrakte Methoden innerhalb der abstrakten Klasse, wie public abstract void LoadData(); und public abstract void SaveData();, ohne sie zu implementieren. Dadurch wird sichergestellt, dass jede abgeleitete Klasse diese Methoden implementieren muss, ähnlich wie es bei Schnittstellen der Fall ist.

Überschreibende Methoden in abstrakten Klassen

Tim erörtert bei (12:56), wie man Methoden in einer abstrakten Klasse außer Kraft setzt. Er zeigt, dass Sie eine Methode in der Basisklasse als virtual deklarieren können, sodass abgeleitete Klassen sie überschreiben können. Dieser Ansatz bietet Flexibilität bei der Implementierung und Erweiterung von Methoden in abgeleiteten Klassen.

Hier ist der Code der abgeleiteten Klasse mit den Methodenüberschreibungen:

// Derived class from abstract base class
public class SQLDataAccessWithAbstract : AbstractDataAccess
{
    // Implementing the abstract LoadData method
    public override void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Implementing the abstract SaveData method
    public override void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}
// Derived class from abstract base class
public class SQLDataAccessWithAbstract : AbstractDataAccess
{
    // Implementing the abstract LoadData method
    public override void LoadData()
    {
        Console.WriteLine("Loading SQL data...");
    }

    // Implementing the abstract SaveData method
    public override void SaveData()
    {
        Console.WriteLine("Saving SQL data...");
    }
}

Wann sollten abstrakte Klassen verwendet werden

Tim (16:01) weist darauf hin, dass abstrakte Klassen nicht jeden Tag verwendet werden sollten, sondern nur in bestimmten Szenarien nützlich sind. Er warnt davor, abstrakte Klassen zu verwenden, nur weil zwei Klassen einen ähnlichen Code haben. Stattdessen betont er die Beibehaltung der "ist ein"-Beziehung und schlägt vor, gegebenenfalls Hilfsmethoden oder -klassen für gemeinsam genutzten Code in Betracht zu ziehen.

Hier ist der Hauptprogrammcode, der die Verwendung demonstriert:

// Main Program
class Program
{
    static void Main(string[] args)
    {
        // Using Base Class
        SQLDataAccess sqlData = new SQLDataAccess();
        Console.WriteLine(sqlData.LoadConnectionString());
        sqlData.LoadData();
        sqlData.SaveData();

        Console.WriteLine("--------------------------");

        // Using Derived Class from Abstract Base Class
        SQLDataAccessWithAbstract sqlDataAbstract = new SQLDataAccessWithAbstract();
        Console.WriteLine(sqlDataAbstract.LoadConnectionString());
        sqlDataAbstract.LoadData();
        sqlDataAbstract.SaveData();

        Console.WriteLine("--------------------------");

        // You can't instantiate Abstract Base Class directly
        // AbstractDataAccess abstractData = new AbstractDataAccess(); 
        // Error: Cannot create an instance of the abstract class
    }
}
// Main Program
class Program
{
    static void Main(string[] args)
    {
        // Using Base Class
        SQLDataAccess sqlData = new SQLDataAccess();
        Console.WriteLine(sqlData.LoadConnectionString());
        sqlData.LoadData();
        sqlData.SaveData();

        Console.WriteLine("--------------------------");

        // Using Derived Class from Abstract Base Class
        SQLDataAccessWithAbstract sqlDataAbstract = new SQLDataAccessWithAbstract();
        Console.WriteLine(sqlDataAbstract.LoadConnectionString());
        sqlDataAbstract.LoadData();
        sqlDataAbstract.SaveData();

        Console.WriteLine("--------------------------");

        // You can't instantiate Abstract Base Class directly
        // AbstractDataAccess abstractData = new AbstractDataAccess(); 
        // Error: Cannot create an instance of the abstract class
    }
}

Abschluss

Tim Coreys tiefer Einblick in C# abstrakte Klassen bietet ein klares und praktisches Verständnis ihres Zwecks, ihrer Funktionalität und ihrer realen Anwendungen. Anhand seiner Demo-Anwendung demonstriert er, wie abstrakte Klassen die Lücke zwischen Basisklassen und Schnittstellen schließen und es Entwicklern ermöglichen, flexible und wartbare Codestrukturen zu erstellen.

Durch die Betonung von Best Practices, wie z. B. die Verwendung abstrakter Klassen in den richtigen Szenarien und die Vermeidung von Überbeanspruchung, gibt Tim den Entwicklern die Mittel an die Hand, um fundierte Designentscheidungen zu treffen. Mit einem soliden Verständnis dieser Konzepte können Entwickler ihre objektorientierten Programmierkenntnisse verbessern und robuste C#-Anwendungen erstellen.

Hero Worlddot related to Abstrakte C#-Klassen verstehen
Hero Affiliate related to Abstrakte C#-Klassen verstehen

Verdienen Sie mehr, indem Sie teilen, was Sie lieben

Erstellen Sie Inhalte für Entwickler, die mit .NET, C#, Java, Python oder Node.js arbeiten? Verwandeln Sie Ihr Fachwissen in ein zusätzliches Einkommen!

Iron Support Team

Wir sind 24 Stunden am Tag, 5 Tage die Woche online.
Chat
E-Mail
Rufen Sie mich an