abstract 適用目標
| 目標 | 效果 |
| 類別 | 不可實例化,可包含抽象/非抽象成員 |
| 方法 | 無實作,衍生類別必須 override 實作 |
| 屬性 | 定義 get/set 契約,衍生類別必須實作對應存取器 |
| 事件 | 定義事件契約,衍生類別必須實作 |
| 索引子 | 定義存取契約,衍生類別必須實作 |
禁止組合
abstract + static ❌
abstract + virtual ❌(abstract 隱含 virtual)
abstract + private ❌(無法被覆寫)
完整範例:幾何形狀體系
using System;
abstract class Shape {
// 抽象唯讀屬性:強制衍生類別實作 get
public abstract double Area { get; }
// 抽象方法:計算周長
public abstract double Perimeter();
// 抽象事件:面積變更通知
public abstract event EventHandler AreaChanged;
// 抽象索引子:依索引取得頂點
public abstract Point this[int index] { get; }
// 非抽象成員:共用邏輯
public void PrintInfo() => Console.WriteLine($"Area: {Area}, Perimeter: {Perimeter}");
}
class Rectangle : Shape {
private double _w, _h;
public Rectangle(double w, double h) { _w = w; _h = h; }
public override double Area => _w * _h;
public override double Perimeter() => 2 * (_w + _h);
public override event EventHandler AreaChanged;
private Point[] _vertices = new Point[4];
public override Point this[int index] => _vertices[index];
}
struct Point { public double X, Y; public Point(double x, double y) { X = x; Y = y; } }
class Program {
static void Main() {
Shape s = new Rectangle(10, 5);
s.PrintInfo(); // Area: 50, Perimeter: 30
Console.ReadKey();
}
}
抽象類別 vs 介面:選擇指南
| 維度 | 抽象類別 | 介面 |
| 多重實作 | 單一繼承 | 多重實作 |
| 共用狀態/邏輯 | ✅ 欄位、建構函式、非抽象方法 | ❌ 無狀態(C# 8.0 前) |
| 存取修飾詞 | 完整支援 | 隱含 public |
| 版本演進 | 新增非抽象成員不破壞 | C# 8.0+ 預設實作可緩解 |
| 結構體適用 | ❌ | ✅ |
Template Method 模式:抽象類別經典應用
abstract class DataProcessor {
// 模板方法:定義演算法骨架
public void Process() {
ReadData();
var data = TransformData(); // 抽象步驟
ValidateData(data); // 抽象步驟
SaveData(data);
NotifyComplete();
}
protected abstract object TransformData();
protected abstract void ValidateData(object data);
// 可選擇覆寫的掛鉤
protected virtual void ReadData() => Console.WriteLine("Reading...");
protected virtual void SaveData(object data) => Console.WriteLine("Saving...");
protected virtual void NotifyComplete() => Console.WriteLine("Done.");
}
class CsvProcessor : DataProcessor {
protected override object TransformData() { /* CSV 解析 */ return new object(); }
protected override void ValidateData(object data) { /* 驗證邏輯 */ }
}
最佳實踐
- 介面定義「能做什麼」,抽象類別定義「是什麼」並共用實作
- 抽象類建構函式設為
protected(防止外部直接 new)
- 抽象成員盡量少而精,核心變化點抽象化
- 提供
virtual 掛鉤而非強制 abstract,給予彈性
- 文檔標註
<inheritdoc/> 繼承介面/基底註解