Dela via


abstrakt (C#-referens)

Modifieraren abstract anger att målet har en implementering som saknas eller är ofullständig. Använd den abstrakta modifieraren med klasser, metoder, egenskaper, indexerare och händelser. abstract Använd modifieraren i en klassdeklaration för att ange att en klass endast är avsedd att vara en basklass för andra klasser, inte instansierad på egen hand. Icke-abstrakta klasser som härleds från den abstrakta klassen måste implementera medlemmar som markerats som abstrakta.

C#-språkreferensen dokumenterar den senaste versionen av C#-språket. Den innehåller även inledande dokumentation för funktioner i offentliga förhandsversioner för den kommande språkversionen.

Dokumentationen identifierar alla funktioner som först introducerades i de tre senaste versionerna av språket eller i aktuella offentliga förhandsversioner.

Tips/Råd

Information om när en funktion först introducerades i C# finns i artikeln om språkversionshistoriken för C#.

Abstrakta klasser kan innehålla både abstrakta medlemmar (som inte har någon implementering och måste åsidosättas i härledda klasser) och fullständigt implementerade medlemmar (till exempel vanliga metoder, egenskaper och konstruktorer). Med den här funktionen kan abstrakta klasser tillhandahålla vanliga funktioner samtidigt som härledda klasser krävs för att implementera specifika abstrakta medlemmar.

Anmärkning

Gränssnittsmedlemmar är abstract som standard.

Abstrakt klass med blandade medlemmar

I följande exempel visas en abstrakt klass som innehåller både implementerade metoder och abstrakta medlemmar:

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
*/

I det här exemplet tillhandahåller den Vehicle abstrakta klassen:

  • Implementerade medlemmar: GetInfo() metod, StartEngine() metod och konstruktor – dessa medlemmar tillhandahåller gemensamma funktioner för alla fordon.
  • Abstrakta medlemmar: Move() metod och MaxSpeed egenskap – dessa medlemmar måste implementeras av varje specifik fordonstyp.

Med den här designen kan den abstrakta klassen tillhandahålla delade funktioner samtidigt som härledda klasser implementerar fordonsspecifikt beteende.

Betongklass härledd från en abstrakt klass

I det här exemplet måste klassen Square tillhandahålla en implementering av GetArea eftersom den härleds från Shape:

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

Abstrakta klasser har följande funktioner:

  • Du kan inte skapa en instans av en abstrakt klass.
  • En abstrakt klass kan innehålla abstrakta metoder och accessorer.
  • En abstrakt klass kan också innehålla implementerade metoder, egenskaper, fält och andra medlemmar som tillhandahåller funktioner för härledda klasser.
  • Du kan inte använda modifieraren i sealed en abstrakt klass eftersom de två modifierarna har motsatta betydelser. Modifieraren sealed förhindrar att en klass ärvs och abstract modifieraren kräver att en klass ärvs.
  • En icke-abstrakt klass som härleds från en abstrakt klass måste innehålla faktiska implementeringar av alla ärvda abstrakta metoder och åtkomstpunkter.

abstract Använd modifieraren i en metod- eller egenskapsdeklaration för att ange att metoden eller egenskapen inte innehåller implementering.

Abstrakta metoder har följande funktioner:

  • En abstrakt metod är implicit en virtuell metod.

  • Abstrakta metoddeklarationer tillåts endast i abstrakta klasser.

  • Eftersom en abstrakt metoddeklaration inte innehåller någon faktisk implementering finns det ingen metodtext. Metoddeklarationen slutar helt enkelt med ett semikolon. Till exempel:

    public abstract void MyMethod();
    

    Implementeringen tillhandahålls av en metod override, som är medlem i en icke-abstrakt klass.

  • Det är ett fel att använda static eller virtual modifierare i en abstrakt metoddeklaration i en class typ. Du kan deklarera static abstract och static virtual metoder i gränssnitt.

    Abstrakta egenskaper fungerar som abstrakta metoder, förutom skillnaderna i deklarations- och anropssyntax.

  • Det är ett fel att använda abstract modifieraren på en statisk egenskap i en class typ. Du kan deklarera static abstract eller static virtual egenskaper i gränssnittsdeklarationer.

  • En abstrakt ärvd egenskap kan åsidosättas i en härledd klass genom att inkludera en egenskapsdeklaration som använder override modifieraren.

Mer information om abstrakta klasser finns i Abstrakta och förseglade klasser och klassmedlemmar.

En abstrakt klass måste tillhandahålla implementering för alla gränssnittsmedlemmar. En abstrakt klass som implementerar ett gränssnitt kan mappa gränssnittsmetoderna till abstrakta metoder. Till exempel:

interface I
{
    void M();
}

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

I följande exempel härleds klassen DerivedClass från en abstrakt klass BaseClass. Den abstrakta klassen innehåller en abstrakt metod, AbstractMethod, och två abstrakta egenskaper och XY .

// 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

Om du i föregående exempel försöker instansiera den abstrakta klassen med hjälp av en instruktion som den här:

BaseClass bc = new BaseClass();   // Error

Du får ett felmeddelande om att kompilatorn inte kan skapa en instans av den abstrakta klassen "BaseClass". Du kan dock använda en abstrakt klasskonstruktor, som du ser i följande exempel.

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

Klassen Shape deklareras abstract, vilket innebär att du inte kan instansiera den direkt. I stället fungerar den som en skiss för andra klasser.

  • Även om du inte kan skapa objekt i en abstrakt klass kan den fortfarande ha en konstruktor. Den här konstruktorn är vanligtvis protected, vilket innebär att endast härledda klasser kan komma åt den. I det här fallet tar Shape konstruktorn en color parameter och initierar egenskapen Color. Det skriver också ut ett meddelande till konsolen. Delen public Square(string color, double side) : base(color) anropar basklassens konstruktor (Shape) och skickar argumentet color till den.
  • Shape I klassen tar den definierade konstruktorn en färg som en parameter protected Shape(string color). Det innebär att C# inte längre tillhandahåller en standardparameterlös konstruktor automatiskt. Härledda klasser måste använda : base(color) uttrycket för att anropa baskonstruktorn. Om du anger standardvärdet till färg protected Shape(string color="green") kan uttrycket utelämnas : base(color) i härledda klasser. Konstruktorn protected Shape(string color="green") anger färgen till grön.

Språkspecifikation för C#

Mer information finns i C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning.

Se även