Dela via


abstrakt (C#-referens)

Modifieraren abstract anger att det som ändras har en implementering som saknas eller är ofullständig. Den abstrakta modifieraren kan användas 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. Medlemmar som är markerade som abstrakta måste implementeras av icke-abstrakta klasser som härleds från den abstrakta klassen.

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). På så sätt kan abstrakta klasser tillhandahålla vanliga funktioner samtidigt som härledda klasser krävs för att implementera specifika abstrakta medlemmar.

Exempel 1 – 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 ger vanliga funktioner för alla fordon.
  • Abstrakta medlemmar: Move() metod och MaxSpeed egenskap – dessa 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.

Exempel 2

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:

  • Det går inte att instansiera 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.

  • Det går inte att ändra en abstrakt klass med den förseglade modifieraren 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 och det finns inga klammerparenteser ({ }) efter signaturen. Till exempel:

    public abstract void MyMethod();  
    

    Implementeringen tillhandahålls av en åsidosättning av metoden, som är medlem i en icke-abstrakt klass.

  • Det är ett fel att använda statiska eller virtuella modifierare i en abstrakt metoddeklaration.

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

  • Det är ett fel att använda modifieraren på abstract en statisk egenskap.

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

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

Exempel 3

I det här exemplet 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".

Det är dock möjligt att använda en abstrakt klasskonstruktor, som i exemplet nedan

Exempel 4

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 den inte kan instansieras 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 den bara kan nås från härledda klasser. 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.
  • I klassen Form tar den definierade konstruktorn en färg som en parameter protected Shape(string color). Det innebär att det inte längre finns någon standardparameterfri konstruktor som tillhandahålls automatiskt av C# och därför måste härledda klasser använda : base(color)-uttrycket för att anropa baskonstruktorn. Om du anger standardvärdet till färg protected Shape(string color="green") kan du utelämna det : base(color) uttrycket i härledda klasser, men den typen av konstruktor protected Shape(string color="green") anropas, vilket gör att färgen blir 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