abstract 修飾詞表示要修改的項目具有遺失或不完整的實作。 抽象修飾詞可以與類別、方法、屬性、索引子和事件搭配使用。 在類別宣告中使用 abstract 修飾詞,來表示某一類別只是要作為其他類別的基底類別,不是自行具現化。 標記為抽象的成員,必須由衍生自抽象類別的非抽象類別實作。
抽象類別可以包含抽象成員 (沒有實作,且必須在衍生類別中覆寫) 和完全實作的成員 (例如一般方法、屬性和建構函式) 。 這允許抽象類別提供通用功能,同時仍然需要派生類別實現特定的抽象成員。
範例 1 - 具有混合成員的抽象類別
下列範例示範同時包含實作方法和抽象成員的抽象類別:
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屬性 - 這些必須由每個特定的車輛類型實現。
這種設計允許抽象類別提供共享功能,同時確保派生類別實現特定於車輛的行為。
範例 2
在此範例中,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 提供了實作,而這個方法是非抽象類別的成員。
抽象屬性的行為類似抽象方法,但宣告和引動過程語法的差異除外。
在靜態屬性上使用
abstract修飾詞是錯誤的。包括使用 override 修飾詞的屬性宣告,即可覆寫衍生類別中的抽象繼承屬性。
如需抽象類別的詳細資訊,請參閱抽象和密封類別以及類別成員。
抽象類別必須提供所有介面成員的實作。
實作介面的抽象類別可能會將介面方法對應至抽象方法。 例如:
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
範例 3
在此範例中,DerivedClass 類別衍生自抽象類別 BaseClass。 抽象類別包含抽象方法 AbstractMethod 和兩個抽象屬性:X 和 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
在上述範例中,如果您嘗試使用如下的陳述式來具現化抽象類別︰
BaseClass bc = new BaseClass(); // Error
您會收到錯誤,指出編譯器無法建立抽象類別 'BaseClass' 的執行個體。
不過,您可以使用抽象類建構函式,如下列範例所示
範例 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()}");
}
}
Shape 類別會宣告為 abstract,這表示無法直接具現化。 相反地,它會作為其他類別的藍圖。
- 雖然您無法建立抽象類的物件,但它仍然可以有建構函式。 此建構函式通常
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# 語法及用法的限定來源。