Teilen über


abstract (C#-Referenz)

Der abstract Modifizierer gibt an, dass das Ziel über eine fehlende oder unvollständige Implementierung verfügt. Verwenden Sie den abstrakten Modifizierer mit Klassen, Methoden, Eigenschaften, Indexern und Ereignissen. Verwenden Sie den abstract-Modifizierer in einer Klassendeklaration, um anzugeben, dass die Klasse nur die Basisklasse für andere Klassen sein und nicht selbst instanziiert werden soll. Nicht abstrakte Klassen, die von der abstrakten Klasse abgeleitet werden, müssen Elemente implementieren, die als abstrakt gekennzeichnet sind.

Die C#-Sprachreferenz dokumentiert die zuletzt veröffentlichte Version der C#-Sprache. Außerdem enthält sie eine erste Dokumentation zu Funktionen in der öffentlichen Vorschau für die kommende Sprachversion.

In der Dokumentation werden alle Features identifiziert, die in den letzten drei Versionen der Sprache oder in der aktuellen öffentlichen Vorschau eingeführt wurden.

Tipp

Informationen dazu, wann ein Feature erstmals in C# eingeführt wurde, finden Sie im Artikel zum Versionsverlauf der C#-Sprache.

Abstrakte Klassen können sowohl abstrakte Member enthalten (die keine Implementierung aufweisen und in abgeleiteten Klassen überschrieben werden müssen) als auch vollständig implementierte Member (z. B. reguläre Methoden, Eigenschaften und Konstruktoren). Mit diesem Feature können abstrakte Klassen allgemeine Funktionen bereitstellen und gleichzeitig abgeleitete Klassen zum Implementieren bestimmter abstrakter Member erforderlich sein.

Hinweis

Schnittstellenmmber sind abstract standardmäßig.

Abstrakte Klasse mit gemischten Elementen

Im folgenden Beispiel wird eine abstrakte Klasse veranschaulicht, die sowohl implementierte Methoden als auch abstrakte Member enthält:

namespace LanguageKeywords;

public abstract class Vehicle
{
    protected string _brand;
    
    // Constructor - implemented method in abstract class
    public Vehicle(string brand) => _brand = brand;
    
    // Implemented method - provides functionality that all vehicles share
    public string GetInfo() => $"This is a {_brand} vehicle.";
    
    // Another implemented method
    public virtual void StartEngine() => Console.WriteLine($"{_brand} engine is starting...");
    
    // Abstract method - must be implemented by derived classes
    public abstract void Move();
    
    // Abstract property - must be implemented by derived classes  
    public abstract int MaxSpeed { get; }
}

public class Car : Vehicle
{
    public Car(string brand) : base(brand) { }
    
    // Implementation of abstract method
    public override void Move() => Console.WriteLine($"{_brand} car is driving on the road.");
    
    // Implementation of abstract property
    public override int MaxSpeed => 200;
}

public class Boat : Vehicle
{
    public Boat(string brand) : base(brand) { }
    
    // Implementation of abstract method
    public override void Move() => Console.WriteLine($"{_brand} boat is sailing on the water.");
    
    // Implementation of abstract property
    public override int MaxSpeed => 50;
}

public class AbstractExample
{
    public static void Examples()
    {
        // Cannot instantiate abstract class: Vehicle v = new Vehicle("Generic"); // Error!
        
        Car car = new Car("Toyota");
        Boat boat = new Boat("Yamaha");
        
        // Using implemented methods from abstract class
        Console.WriteLine(car.GetInfo());
        car.StartEngine();
        
        // Using abstract methods implemented in derived class
        car.Move();
        Console.WriteLine($"Max speed: {car.MaxSpeed} km/h");
        
        Console.WriteLine();
        
        Console.WriteLine(boat.GetInfo());
        boat.StartEngine();
        boat.Move();
        Console.WriteLine($"Max speed: {boat.MaxSpeed} km/h");
    }
}

class Program
{
    static void Main()
    {
        AbstractExample.Examples();
    }
}
/* Output:
This is a Toyota vehicle.
Toyota engine is starting...
Toyota car is driving on the road.
Max speed: 200 km/h

This is a Yamaha vehicle.
Yamaha engine is starting...
Yamaha boat is sailing on the water.
Max speed: 50 km/h
*/

In diesem Beispiel stellt die Vehicle abstrakte Klasse Folgendes bereit:

  • Implementierte Member: GetInfo() Methode, StartEngine() Methode und Konstruktor – diese Member bieten allgemeine Funktionen für alle Fahrzeuge.
  • Abstrakte Elemente: Move() Methode und MaxSpeed Eigenschaft - diese Member müssen von jedem bestimmten Fahrzeugtyp implementiert werden.

Mit diesem Design kann die abstrakte Klasse gemeinsam genutzte Funktionen bereitstellen und gleichzeitig sicherstellen, dass abgeleitete Klassen fahrzeugspezifisches Verhalten implementieren.

Von einer abstrakten Klasse abgeleitete konkrete Klasse

In diesem Beispiel muss die Klasse Square eine Implementierung von GetArea bereitstellen, da sie von Shape abgeleitet ist:

abstract class Shape
{
    public abstract int GetArea();
}

class Square : Shape
{
    private int _side;

    public Square(int n) => _side = n;

    // GetArea method is required to avoid a compile-time error.
    public override int GetArea() => _side * _side;

    static void Main()
    {
        var sq = new Square(12);
        Console.WriteLine($"Area of the square = {sq.GetArea()}");
    }
}
// Output: Area of the square = 144

Abstrakte Klassen weisen die folgenden Funktionen auf:

  • Sie können keine Instanz einer abstrakten Klasse erstellen.
  • Eine abstrakte Klasse kann abstrakte Methoden und Accessoren enthalten.
  • Eine abstrakte Klasse kann auch implementierte Methoden, Eigenschaften, Felder und andere Member enthalten, die Funktionen für abgeleitete Klassen bereitstellen.
  • Sie können den sealed Modifizierer nicht für eine abstrakte Klasse verwenden, da die beiden Modifizierer eine entgegengesetzte Bedeutung haben. Der sealed-Modifizierer verhindert das Vererben einer Klasse, und der abstract-Modifizierer erfordert das Vererben einer Klasse.
  • Eine nicht abstrakte Klasse, die von einer abstrakten Klasse abgeleitet wurde, muss Implementierungen aller geerbten abstrakten Methoden und Accessoren enthalten.

Verwenden Sie den abstract Modifizierer in einer Methode oder Eigenschaftsdeklaration, um anzugeben, dass die Methode oder Eigenschaft keine Implementierung enthält.

Abstrakte Methoden weisen die folgenden Funktionen auf:

  • Eine abstrakte Methode ist implizit eine virtuelle Methode.

  • Abstrakte Methodendeklarationen sind nur in abstrakten Klassen zulässig.

  • Da eine abstrakte Methodendeklaration keine tatsächliche Implementierung bereitstellt, gibt es keinen Methodentext. Die Methodendeklaration endet einfach mit einem Semikolon. Beispiel:

    public abstract void MyMethod();
    

    Die Implementierung wird durch eine Methode overridebereitgestellt, die ein Mitglied einer nicht abstrakten Klasse ist.

  • Es ist ein Fehler, die staticvirtual Modifizierer in einer abstrakten Methodendeklaration in einem class Typ zu verwenden. Sie können Schnittstellen deklarieren und static virtual Methoden verwendenstatic abstract.

    Abstrakte Eigenschaften verhalten sich wie abstrakte Methoden – sie unterscheiden sich lediglich in der Deklarations- und Aufrufsyntax.

  • Es ist ein Fehler, den abstract Modifizierer für eine statische Eigenschaft in einem class Typ zu verwenden. Sie können schnittstellendeklarationen oder static virtual Eigenschaften deklarierenstatic abstract.

  • Eine abstrakte geerbte Eigenschaft kann in einer abgeleiteten Klasse überschrieben werden, indem eine Eigenschaftsdeklaration eingeschlossen wird, die den override Modifizierer verwendet.

Weitere Informationen zu abstrakten Klassen finden Sie unter Abstrakte und versiegelte Klassen und Klassenmember.

Eine abstrakte Klasse muss eine Implementierung für alle Schnittstellenmember bereitstellen. Eine abstrakte Klasse, die eine Schnittstelle implementiert, ordnet die Schnittstellenmethoden möglicherweise abstrakten Methoden zu. Beispiel:

interface I
{
    void M();
}

abstract class C : I
{
    public abstract void M();
}

Im folgenden Beispiel wird die Klasse DerivedClass von einer abstrakten Klasse BaseClassabgeleitet. Die abstrakte Klasse enthält eine abstrakte Methode, AbstractMethod, und zwei abstrakte Eigenschaften, X und Y.

// Abstract class
abstract class BaseClass
{
    protected int _x = 100;
    protected int _y = 150;

    // Abstract method
    public abstract void AbstractMethod();

    // Abstract properties
    public abstract int X { get; }
    public abstract int Y { get; }
}

class DerivedClass : BaseClass
{
    public override void AbstractMethod()
    {
        _x++;
        _y++;
    }

    public override int X   // overriding property
    {
        get
        {
            return _x + 10;
        }
    }

    public override int Y   // overriding property
    {
        get
        {
            return _y + 10;
        }
    }

    static void Main()
    {
        var o = new DerivedClass();
        o.AbstractMethod();
        Console.WriteLine($"x = {o.X}, y = {o.Y}");
    }
}
// Output: x = 111, y = 161

Wenn Sie beim vorherigen Beispiel versuchen, die abstrakte Klasse mithilfe des folgenden Anweisungsbeispiels zu instanziieren:

BaseClass bc = new BaseClass();   // Error

Sie erhalten eine Fehlermeldung, die besagt, dass der Compiler keine Instanz der abstrakten Klasse "BaseClass" erstellen kann. Dennoch können Sie einen abstrakten Klassenkonstruktor verwenden, wie im folgenden Beispiel gezeigt.

public abstract class Shape
{
    public string Color { get; set; }

    // Constructor of the abstract class
    protected Shape(string color)
    {
        Color = color;
        Console.WriteLine($"Created a shape with color {color}.");
    }

    // Abstract method that must be implemented by derived classes
    public abstract double CalculateArea();
}

public class Square : Shape
{
    public double Side { get; set; }

    // Constructor of the derived class calling the base class constructor
    public Square(string color, double side) : base(color)
    {
        Side = side;
    }

    public override double CalculateArea()
    {
        return Side * Side;
    }
}

public class Program
{
    public static void Main(string[] args)
     {
            Square square = new Square("red", 5);
            Console.WriteLine($"Area of the square: {square.CalculateArea()}");            
     }
}

Die Shape Klasse wird deklariert abstract, was bedeutet, dass Sie sie nicht direkt instanziieren können. Stattdessen dient sie als Blaupause für andere Klassen.

  • Obwohl Sie keine Objekte einer abstrakten Klasse erstellen können, kann sie dennoch über einen Konstruktor verfügen. Dieser Konstruktor ist in der Regel protected, was bedeutet, dass nur abgeleitete Klassen darauf zugreifen können. In diesem Fall verwendet der Shape-Konstruktor einen color-Parameter und initialisiert die Color-Eigenschaft. Außerdem wird eine Meldung auf der Konsole ausgegeben. Der public Square(string color, double side) : base(color)-Teil ruft den Konstruktor der Basisklasse (Shape) auf und übergibt das Argument color an ihn.
  • In der Shape Klasse akzeptiert der definierte Konstruktor eine Farbe als Parameter protected Shape(string color). Dies bedeutet, dass C# keinen standardmäßigen parameterlosen Konstruktor automatisch bereitstellt. Abgeleitete Klassen müssen den : base(color) Ausdruck verwenden, um den Basiskonstruktor aufzurufen. Durch Festlegen des Standardwerts auf Farbe protected Shape(string color="green") wird der : base(color) Ausdruck in abgeleiteten Klassen weggelassen. Der Konstruktor protected Shape(string color="green") legt die Farbe auf Grün fest.

C#-Programmiersprachenspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch