共用方式為


abstract (C# 參考)

abstract修飾符表示其目標有缺失或不完整的實作。 使用帶有類別、方法、屬性、索引器和事件的抽象修飾符。 在類別宣告中使用 abstract 修飾詞,來表示某一類別只是要作為其他類別的基底類別,不是自行具現化。 從抽象類別衍生的非抽象類別必須實作標記為抽象的成員。

C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。

文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。

小提示

欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。

抽象類別可以包含抽象成員 (沒有實作,且必須在衍生類別中覆寫) 和完全實作的成員 (例如一般方法、屬性和建構函式) 。 此功能允許抽象類別提供共通功能,同時仍需派生類別實作特定的抽象成員。

備註

介面成員預設為 abstract

混合成員的抽象類別

下列範例示範同時包含實作方法和抽象成員的抽象類別:

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屬於非抽象類別。

  • 在型別中用 static or virtual 修改器來宣告抽象方法宣告 class 是錯誤的。 你可以在介面中宣告 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()}");            
     }
}

Shape 類別被宣告為 abstract,表示你無法直接實例化它。 相反地,它會作為其他類別的藍圖。

  • 雖然您無法建立抽象類的物件,但它仍然可以有建構函式。 此建構子通常是 protected,意即只有導出類別能存取。 在此情況下,Shape 建構函式會採用 color 參數,並初始化 Color 屬性。 它也會將訊息列印至主控台。 public Square(string color, double side) : base(color) 元件會呼叫基類的建構函式(Shape),並將 color 自變數傳遞給它。
  • 在類別 Shape 中,定義的建構子以 protected Shape(string color)顏色為參數。 這表示 C# 不再自動提供預設無參數建構子。 衍生類別必須使用該 : base(color) 表達式來呼叫基底建構子。 將預設值設為 color protected Shape(string color="green") ,則可在衍生類別中省略該表達式 : base(color) 。 建構者 protected Shape(string color="green") 將顏色設定為綠色。

C# 語言規格

如需詳細資訊,請參閱<C# 語言規格>。 語言規格是 C# 語法及用法的限定來源。

另請參閱