abstract(C# 参考)

修饰 abstract 符指示其目标缺少或不完整的实现。 将抽象修饰符与类、方法、属性、索引器和事件一起使用。 在类声明中使用 abstract 修饰符来指示某个类仅用作其他类的基类,而不用于自行进行实例化。 派生自抽象类的非抽象类必须实现标记为抽象的成员。

C# 语言参考记录了 C# 语言的最新发布版本。 它还包含即将发布的语言版本公共预览版中功能的初始文档。

本文档标识了在语言的最后三个版本或当前公共预览版中首次引入的任何功能。

小窍门

若要查找 C# 中首次引入功能时,请参阅 有关 C# 语言版本历史记录的文章。

抽象类可以包含抽象成员(这些成员没有实现,必须在派生类中重写)和完全实现的成员(如常规方法、属性和构造函数)。 此功能允许抽象类提供通用功能,同时仍要求派生类实现特定的抽象成员。

注释

接口成员默认为 />。

包含混合成员的抽象类

以下示例演示包含实现的方法和抽象成员的抽象类:

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

在此示例中, Vehicle 抽象类提供:

  • 实现的成员GetInfo() 方法、 StartEngine() 方法和构造函数 - 这些成员为所有车辆提供通用功能。
  • 抽象成员Move() 方法和 MaxSpeed 属性 - 这些成员必须由每个特定的车辆类型实现。

此设计允许抽象类提供共享功能,同时确保派生类实现特定于车辆的行为。

派生自抽象类的具体类

在此示例中,类 Square 必须提供 GetArea 的实现,因为它派生自 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

抽象类具有以下功能:

  • 不能创建抽象类的实例。
  • 抽象类可以包含抽象方法和访问器。
  • 抽象类还可以包含实现的方法、属性、字段和为派生类提供功能的其他成员。
  • 不能对 sealed 抽象类使用修饰符,因为两个修饰符的含义相反。 sealed 修饰符阻止类被继承,而 abstract 修饰符要求类被继承。
  • 派生自抽象类的非抽象类,必须包含全部已继承的抽象方法和访问器的实际实现。

abstract使用方法或属性声明中的修饰符指示方法或属性不包含实现。

抽象方法具有以下功能:

  • 抽象方法是隐式的虚拟方法。

  • 只有抽象类中才允许抽象方法声明。

  • 由于抽象方法声明不提供实际实现,因此没有方法主体。 方法声明只是以分号结尾。 例如:

    public abstract void MyMethod();
    

    实现由方法 override提供,该方法是非抽象类的成员。

  • 在类型中的抽象方法声明中class使用static修饰virtual符是错误的。 可以在接口中声明 static abstractstatic virtual 方法。

    除了声明和调用语法方面不同外,抽象属性的行为与抽象方法相似。

  • 对类型中的class静态属性使用abstract修饰符是错误的。 可以在接口声明中声明 static abstractstatic virtual 属性。

  • 可以通过包括使用 override 修饰符的属性声明,在派生类中重写抽象继承属性。

有关抽象类的详细信息,请参阅抽象类、密封类及类成员

抽象类必须为所有接口成员提供实现。 实现接口的抽象类有可能将接口方法映射到抽象方法上。 例如:

interface I
{
    void M();
}

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

在下面的示例中,类 DerivedClass 派生自抽象类 BaseClass。 抽象类包含抽象方法 AbstractMethod,以及两个抽象属性 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

在前面的示例中,如果你尝试通过使用如下语句来实例化抽象类:

BaseClass bc = new BaseClass();   // Error

出现错误,指出编译器无法创建抽象类“BaseClass”的实例。 尽管如此,也可以使用抽象类构造函数,如以下示例所示。

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

abstract声明类Shape,这意味着无法直接实例化它。 相反,它充当其他类的蓝图。

  • 即使无法创建抽象类的对象,它仍然可以有构造函数。 此构造函数通常 protected意味着只有派生类可以访问它。 在这种情况下,Shape 构造函数采用 color 参数并初始化 Color 属性。 它还将消息输出到控制台。 public Square(string color, double side) : base(color) 部件调用基类的构造函数(Shape),并将 color 参数传递给它。
  • 在类中 Shape ,定义的构造函数采用颜色作为参数 protected Shape(string color)。 这意味着 C# 不再自动提供默认无参数构造函数。 派生类必须使用 : base(color) 表达式来调用基构造函数。 将默认值设置为颜色 protected Shape(string color="green") 允许省 : base(color) 略派生类中的表达式。 构造函数 protected Shape(string color="green") 将颜色设置为绿色。

C# 语言规范

有关详细信息,请参阅 C# 语言规范。 该语言规范是 C# 语法和用法的权威资料。

另请参阅