Search
Close this search box.
Eine abstrakte Klasse in C#

C# Abstrakte Klassen - Definition, Anwendung und Vorteile

In der objektorientierten Programmierung spielt die Abstraktion eine wichtige Rolle, um komplexe Systeme zu modellieren und zu implementieren. Eine Möglichkeit der Abstraktion in C# sind abstrakte Klassen. Abstrakte Klassen sind eine Art von Klassen, die nicht direkt instanziiert werden können, sondern als Vorlage für andere Klassen dienen. In diesem Artikel werden wir uns genauer mit dem Thema C# abstrakte Klassen befassen, ihre Definition, Anwendung und Vorteile erläutern.

Definition von C# Abstrakten Klassen: Eine abstrakte Klasse in C# ist eine Klasse, die nicht direkt instanziiert werden kann und mindestens eine abstrakte Methode enthält. Abstrakte Methoden sind Methoden, die keinen Code enthalten und in abgeleiteten Klassen überschrieben werden müssen. Abstrakte Klassen können jedoch auch konkrete Methoden enthalten, die nicht abstrakt sind und implementiert werden können.

Anwendung von C# Abstrakten Klassen: Abstrakte Klassen werden oft als Vorlage für andere Klassen verwendet, um eine gemeinsame Basisfunktionalität bereitzustellen. Abstrakte Klassen können auch als Schnittstelle zwischen verschiedenen Klassen dienen, um die Wiederverwendbarkeit und Flexibilität des Codes zu erhöhen. Ein Beispiel für die Anwendung von abstrakten Klassen in C# ist die Erstellung einer abstrakten Klasse „Fahrzeug“, die als Vorlage für verschiedene Arten von Fahrzeugen wie Autos, Flugzeugen und Schiffen verwendet werden kann. Diese abgeleiteten Klassen können die abstrakten Methoden der Basis-Klasse überschreiben und gleichzeitig die konkreten Methoden erben.

Vorteile von C# Abstrakten Klassen: Abstrakte Klassen bieten mehrere Vorteile, darunter:

  1. Wiederverwendbarkeit von Code: Abstrakte Klassen können als Vorlage für andere Klassen dienen, was die Wiederverwendbarkeit von Code erhöht und die Implementierung von ähnlichen Klassen vereinfacht.

  2. Flexibilität: Abstrakte Klassen können als Schnittstelle zwischen verschiedenen Klassen dienen, was die Flexibilität des Codes erhöht. Durch die Verwendung von abstrakten Klassen können Klassen unterschiedlicher Typen als Objekte der gleichen Schnittstelle behandelt werden.

  3. Abstraktion: Abstrakte Klassen ermöglichen es, eine gemeinsame Basisfunktionalität zu definieren und somit eine höhere Abstraktionsebene zu erreichen. Dies erleichtert die Implementierung von komplexen Systemen.

  4. Übersichtlichkeit: Abstrakte Klassen können dazu beitragen, den Code übersichtlicher und strukturierter zu gestalten. Durch die Verwendung von abstrakten Klassen wird der Code in abstrakte und konkrete Klassen unterteilt, was die Lesbarkeit und Wartbarkeit des Codes erhöht.

Beispiel-Code zur Abstrakten Klasse: Hier ist ein Beispiel-Code zur Abstrakten Klasse in C#:

				
					public abstract class Fahrzeug
    {
        public abstract void Beschleunigen();
        public abstract void Bremsen();
        public abstract void Tanken();

        public virtual void Starten()
        {
            Console.WriteLine("Das Fahrzeug startet.");
        }

    }
    public class Auto : Fahrzeug
    {
        public override void Beschleunigen()
        {
            Console.WriteLine("Das Auto beschleunigt.");
        }


        public override void Bremsen()
        {
            Console.WriteLine("Das Auto bremst.");
        }

        public override void Tanken()
        {
            Console.WriteLine("Das Auto wird betankt.");
        }
    }

    public class Motorrad : Fahrzeug
    {
        public override void Beschleunigen()
        {
            Console.WriteLine("Das Motorrad beschleunigt.");
        }


        public override void Bremsen()
        {
            Console.WriteLine("Das Motorrad bremst.");
        }

        public override void Tanken()
        {
            Console.WriteLine("Das Motorrad wird betankt.");
        }
    }

    public class Lastwagen : Fahrzeug
    {
        public override void Beschleunigen()
        {
            Console.WriteLine("Der Lastwagen beschleunigt.");
        }


        public override void Bremsen()
        {
            Console.WriteLine("Der Lastwagen bremst.");
        }

        public override void Tanken()
        {
            Console.WriteLine("Der Lastwagen wird betankt.");
        }

        public override void Starten()
        {
            Console.WriteLine("Der Lastwagen startet mit einem lauten Brummen.");
        }

        public class Program
        {
            static void Main(string[] args)
            {
                Fahrzeug auto = new Auto();
                auto.Starten();
                auto.Beschleunigen();
                auto.Bremsen();
                auto.Tanken();
                Fahrzeug motorrad = new Motorrad();
                motorrad.Starten();
                motorrad.Beschleunigen();
                motorrad.Bremsen();
                motorrad.Tanken();

                Fahrzeug lastwagen = new Lastwagen();
                lastwagen.Starten();
                lastwagen.Beschleunigen();
                lastwagen.Bremsen();
                lastwagen.Tanken();
            }
        }
    }
				
			

Dieser Code demonstriert die Verwendung von abstrakten Klassen in C#. In diesem Beispiel wurde eine abstrakte Klasse „Fahrzeug“ erstellt, die allgemeine Methoden enthält, die für alle Arten von Fahrzeugen gelten, wie zum Beispiel Beschleunigen, Bremsen und Tanken. Die Methode „Starten“ ist als virtuell definiert, um eine Standardimplementierung bereitzustellen, die von den abgeleiteten Klassen überschrieben werden kann.

Dann wurden drei spezifische Fahrzeugklassen erstellt: Auto, Motorrad und Lastwagen. Jede dieser Klassen erbt von der abstrakten Klasse „Fahrzeug“ und implementiert ihre eigenen Versionen der abstrakten Methoden. Der Lastwagen überschreibt auch die Methode „Starten“, um ein spezifisches Startverhalten zu haben.

Im Hauptprogramm wurden dann Objekte der jeweiligen Fahrzeugklassen erstellt und als Objekte der abstrakten Klasse „Fahrzeug“ behandelt. Dadurch können die Methoden der abstrakten Klasse aufgerufen werden, und je nach tatsächlichem Objekt werden die spezifischen Implementierungen ausgeführt.

Dieser Code zeigt, wie abstrakte Klassen genutzt werden können, um gemeinsame Methoden und Eigenschaften zu definieren und spezifische Implementierungen in den abgeleiteten Klassen bereitzustellen. Abstrakte Klassen sind eine leistungsstarke Funktion der OOP, die es Entwicklern ermöglicht, die Wiederverwendbarkeit und Flexibilität ihres Codes zu erhöhen.

 

Hier sind weitere Beispiele für die Verwendung von abstrakten Klassen in C#:

Abstrakte Klasse für ein Spielcharakter-System:
Angenommen, Sie schreiben ein Computerspiel und müssen verschiedene Charaktere erstellen, die unterschiedliche Fähigkeiten und Eigenschaften haben. Sie können eine abstrakte Klasse „Charakter“ erstellen, die allgemeine Eigenschaften und Methoden für alle Charaktere enthält. Jede spezifische Charakterklasse würde dann von der abstrakten Klasse „Charakter“ erben und ihre eigenen Implementierungen für die abstrakten Methoden bereitstellen. Beispielsweise könnten Sie eine Methode „Angreifen“ definieren, die die spezifischen Details für den Angriff eines Charakters enthält.

Hier ist der Code für die abstrakte Klasse und ein Beispiel für eine spezifische Charakterklasse:

				
					public abstract class Charakter
{
    public string Name { get; set; }
    public int Leben { get; set; }
    public int Angriffsstärke { get; set; }

    public abstract void Angreifen(Charakter ziel);
    public abstract void Verteidigen(int schaden);
}

public class Krieger : Charakter
{
    public override void Angreifen(Charakter ziel)
    {
        Console.WriteLine($"{Name} greift {ziel.Name} mit einem Schwert an und verursacht {Angriffsstärke} Schaden.");
        ziel.Verteidigen(Angriffsstärke);
    }

    public override void Verteidigen(int schaden)
    {
        Leben -= schaden;
        Console.WriteLine($"{Name} verteidigt sich mit seinem Schild und erleidet {schaden} Schaden. Verbleibende Lebenspunkte: {Leben}");
    }
}

				
			

In diesem Beispiel enthält die abstrakte Klasse „Charakter“ allgemeine Eigenschaften und Methoden für alle Charaktere, einschließlich Name, Lebenspunkte und Angriffsstärke. Die Methoden „Angreifen“ und „Verteidigen“ sind abstrakt und müssen von jeder spezifischen Charakterklasse implementiert werden.

Die Klasse „Krieger“ erbt von der abstrakten Klasse „Charakter“ und implementiert ihre eigenen Versionen von „Angreifen“ und „Verteidigen“. Wenn ein Krieger angreift, verwendet er ein Schwert und verursacht Schaden an seinem Ziel. Wenn er angegriffen wird, verteidigt er sich mit seinem Schild und erleidet Schaden.

Dies ist nur ein Beispiel, und es können viele verschiedene Charakterklassen mit unterschiedlichen Fähigkeiten und Eigenschaften erstellt werden, indem sie von der abstrakten Klasse „Charakter“ erben und ihre eigenen Implementierungen bereitstellen.

Abstrakte Klasse für eine Datenbank-Verbindung: Angenommen, Sie schreiben eine Anwendung, die mit einer Datenbank arbeitet. Sie können eine abstrakte Klasse „Datenbankverbindung“ erstellen, die allgemeine Eigenschaften und Methoden für die Verbindung mit einer Datenbank enthält. Jede spezifische Datenbankklasse würde dann von der abstrakten Klasse „Datenbankverbindung“ erben und ihre eigenen Implementierungen für die abstrakten Methoden bereitstellen. Beispielsweise könnten Sie eine Methode „Verbinden“ definieren, die die spezifischen Details für die Verbindung mit einer bestimmten Datenbank enthält.

Hier ist der Code für die abstrakte Klasse „Datenbankverbindung“ und eine spezifische Klasse „MySQLDatenbank“:

				
					public abstract class Datenbankverbindung
{
    public abstract void Verbinden();
    public abstract void Abfragen(string query);
    public abstract void Trennen();
}

public class MySQLDatenbank : Datenbankverbindung
{
    private string connectionString;

    public MySQLDatenbank(string connectionString)
    {
        this.connectionString = connectionString;
    }

    public override void Verbinden()
    {
        // Code zum Verbinden mit der MySQL-Datenbank
        Console.WriteLine("Verbindung zur MySQL-Datenbank hergestellt.");
    }

    public override void Abfragen(string query)
    {
        // Code zum Ausführen von Abfragen auf der MySQL-Datenbank
        Console.WriteLine($"Die Abfrage \"{query}\" wurde erfolgreich auf der MySQL-Datenbank ausgeführt.");
    }

    public override void Trennen()
    {
        // Code zum Trennen der Verbindung zur MySQL-Datenbank
        Console.WriteLine("Verbindung zur MySQL-Datenbank getrennt.");
    }
}

				
			

Die abstrakte Klasse „Datenbankverbindung“ definiert drei abstrakte Methoden: „Verbinden“, „Abfragen“ und „Trennen“. Die Klasse „MySQLDatenbank“ erbt von der abstrakten Klasse „Datenbankverbindung“ und implementiert die abstrakten Methoden. In diesem Beispiel wird eine spezifische Implementierung für die MySQL-Datenbank gezeigt. Beim Erstellen eines Objekts der Klasse „MySQLDatenbank“ muss eine Verbindungszeichenfolge (connection string) als Parameter übergeben werden.

Abstrakte Klasse für ein Zahlensystem: Angenommen, Sie schreiben eine Anwendung, die mit verschiedenen Arten von Zahlensystemen wie Dezimal-, Binär- und Hexadezimalzahlen arbeitet. Sie können eine abstrakte Klasse „Zahl“ erstellen, die allgemeine Eigenschaften und Methoden für alle Arten von Zahlen enthält. Jede spezifische Zahlklasse würde dann von der abstrakten Klasse „Zahl“ erben und ihre eigenen Implementierungen für die abstrakten Methoden bereitstellen. Beispielsweise könnten Sie eine Methode „Konvertieren“ definieren, die die spezifischen Details für die Konvertierung einer bestimmten Zahl in ein anderes Zahlensystem enthält.

Hier ist der Code für die abstrakte Klasse für ein Zahlensystem:

				
					public abstract class Zahl
{
    protected int wert;

    public Zahl(int wert)
    {
        this.wert = wert;
    }

    public abstract string Konvertieren();
}

				
			

In diesem Beispiel wird die abstrakte Klasse „Zahl“ definiert, die eine Eigenschaft „wert“ und eine abstrakte Methode „Konvertieren“ enthält. Die Eigenschaft „wert“ wird verwendet, um den numerischen Wert der Zahl zu speichern, während die abstrakte Methode „Konvertieren“ von den spezifischen Zahlklassen implementiert wird, um eine Konvertierung in ein anderes Zahlensystem durchzuführen.

Hier ist ein Beispiel für eine spezifische Zahlklasse, die von der abstrakten Klasse „Zahl“ erbt:

				
					public class Dezimalzahl : Zahl
{
    public Dezimalzahl(int wert) : base(wert)
    {
    }

    public override string Konvertieren()
    {
        return wert.ToString();
    }
}

				
			

In diesem Beispiel wird die spezifische Zahlklasse „Dezimalzahl“ definiert, die von der abstrakten Klasse „Zahl“ erbt. Die Klasse implementiert die abstrakte Methode „Konvertieren“, um eine Konvertierung in eine Dezimalzahl durchzuführen, indem sie einfach den Wert der Zahl in einen String umwandelt.

Hier ist ein weiteres Beispiel für eine spezifische Zahlklasse, die von der abstrakten Klasse „Zahl“ erbt:

				
					public class Binaerzahl : Zahl
{
    public Binaerzahl(int wert) : base(wert)
    {
    }

    public override string Konvertieren()
    {
        return Convert.ToString(wert, 2);
    }
}

				
			

In diesem Beispiel wird die spezifische Zahlklasse „Binaerzahl“ definiert, die von der abstrakten Klasse „Zahl“ erbt. Die Klasse implementiert die abstrakte Methode „Konvertieren“, um eine Konvertierung in eine Binaerzahl durchzuführen, indem sie die „Convert.ToString“ Methode verwendet, um den Wert der Zahl in eine Binaerzahl umzuwandeln.

Diese Beispiele zeigen, wie Abstrakte Klassen in C# verwendet werden können, um eine gemeinsame Funktionalität zu definieren, die von einer Gruppe von Klassen gemeinsam genutzt werden kann. Abstrakte Klassen helfen dabei, den Code strukturierter und leichter wartbar zu machen, indem sie eine klare Hierarchie von Klassen und Methoden definieren.

Zusammenfassend lässt sich sagen, dass abstrakte Klassen in C# eine wichtige Rolle bei der Erstellung von hierarchischen Klassenstrukturen spielen. Abstrakte Klassen dienen als Baupläne für spezialisierte Klassen und definieren dabei die Grundlage für die abgeleiteten Klassen. Durch die Verwendung von abstrakten Klassen können Entwickler eine gemeinsame Basis für Klassen mit ähnlichen Eigenschaften und Methoden schaffen, wodurch Code-Wiederholungen vermieden und die Wartbarkeit und Erweiterbarkeit der Anwendung verbessert werden können. Mit Hilfe von abstrakten Klassen können Entwickler zudem das Konzept der Vererbung nutzen, um vorhandene Funktionalitäten von einer Basis-Klasse zu erben und sie in spezialisierten Klassen zu erweitern oder zu überschreiben. Die Verwendung von abstrakten Klassen erfordert jedoch ein gutes Verständnis der OOP-Prinzipien und sollte sorgfältig geplant und umgesetzt werden, um die maximale Effektivität und Nutzen zu erzielen.

Aufgabe:

Aufgabe zum Mitmachen:

Aufgabe: Erstelle eine Klasse namens „Person“ mit den folgenden Attributen:

  • Vorname
  • Nachname
  • Alter

Erstelle dann eine abstrakte Klasse namens „Mitarbeiter“, die von der Klasse „Person“ erbt und die folgenden abstrakten Methoden enthält:

  • BerechneGehalt(): eine Methode, die das Gehalt des Mitarbeiters berechnet und zurückgibt.
  • GebeMitarbeiterInfoAus(): eine Methode, die die Informationen des Mitarbeiters auf der Konsole ausgibt.

Erstelle dann drei spezifische Mitarbeiterklassen:

  • VollzeitMitarbeiter: Ein Vollzeitmitarbeiter hat einen Stundenlohn und arbeitet 40 Stunden pro Woche. Das Gehalt des Mitarbeiters wird als Stundenlohn multipliziert mit 40 multipliziert.
  • TeilzeitMitarbeiter: Ein Teilzeitmitarbeiter hat einen Stundenlohn und arbeitet weniger als 40 Stunden pro Woche. Das Gehalt des Mitarbeiters wird als Stundenlohn multipliziert mit der Anzahl der Arbeitsstunden pro Woche berechnet.
  • Praktikant: Ein Praktikant hat kein Gehalt.

Erstelle jeweils die Klasse mit der entsprechenden Methode BerechneGehalt(). Die Methode GebeMitarbeiterInfoAus() sollte für alle Mitarbeiterklassen gleich sein und den Namen, das Alter und das Gehalt des Mitarbeiters ausgeben.

Um die Lösung anzuzeigen, fahre mit der Maus in die Mitte des darunterliegenden Fensters.

				
					using System;

public class Person
{
    public string Vorname { get; set; }
    public string Nachname { get; set; }
    public int Alter { get; set; }
}

public abstract class Mitarbeiter : Person
{
    public abstract double BerechneGehalt();
    public void GebeMitarbeiterInfoAus()
    {
        Console.WriteLine($"Name: {Vorname} {Nachname}\nAlter: {Alter}\nGehalt: {BerechneGehalt()} Euro");
    }
}

public class VollzeitMitarbeiter : Mitarbeiter
{
    public double Stundenlohn { get; set; }

    public override double BerechneGehalt()
    {
        return Stundenlohn * 40;
    }
}

public class TeilzeitMitarbeiter : Mitarbeiter
{
    public double Stundenlohn { get; set; }
    public int ArbeitsstundenProWoche { get; set; }

    public override double BerechneGehalt()
    {
        return Stundenlohn * ArbeitsstundenProWoche;
    }
}

public class Praktikant : Mitarbeiter
{
    public override double BerechneGehalt()
    {
        return 0;
    }
}

				
			
Zurück zum vorherigen Teil des C# Kurses
Klicken Sie auf den Pfeil, um zum vorherigen Teil des Kurses zurückzukehren
Pfeil-Button zum nächsten Teil des Kurses
Klicken Sie auf den Pfeil, um zum nächsten Teil des Kurses zu gelangen