| 特性 | 虛擬方法 | 抽象方法/類別 | 介面 |
|---|---|---|---|
| 關鍵字 | virtual / override | abstract | interface |
| 基類可具實作 | 是 | 否(抽象方法無主體) | 否(C# 8.0 前) |
| 衍生類強制實作 | 否(可選擇 override) | 是 | 是 |
| 多重實作 | 單一繼承 | 單一繼承 | 多介面實作 |
| 可包含欄位/建構子 | 是 | 是 | 否 |
| 存取修飾詞 | 任意 | 任意 | 預設 public,不可標記 |
| 靜態成員 | 可 | 可 | 不可(C# 8.0 允許 static 靜態方法) |
public class Animal {
public virtual void Speak() {
Console.WriteLine("動物發出聲音");
}
}
public class Dog : Animal {
public override void Speak() {
Console.WriteLine("汪汪!");
}
}
public class Cat : Animal {
// 不覆寫,使用基類預設
}
public abstract class Shape {
public abstract double Area(); // 強制實作
public abstract double Perimeter();
// 共享實作
public void PrintInfo() {
Console.WriteLine($"面積: {Area():F2}, 周長: {Perimeter():F2}");
}
}
public class Circle : Shape {
public double Radius { get; set; }
public override double Area() => Math.PI * Radius * Radius;
public override double Perimeter() => 2 * Math.PI * Radius;
}
public interface ISerializable {
string Serialize();
void Deserialize(string data);
}
public interface ICloneable {
T Clone();
}
// 類別可同時實作多個介面
public class UserProfile : ISerializable, ICloneable {
public string Name { get; set; }
public int Age { get; set; }
public string Serialize() => $"{Name}|{Age}";
public void Deserialize(string data) {
var p = data.Split('|');
Name = p[0]; Age = int.Parse(p[1]);
}
public UserProfile Clone() => new UserProfile { Name = this.Name, Age = this.Age };
}
public interface ILogger {
void Log(string msg);
void LogWarning(string msg) => Log($"WARN: {msg}"); // 預設實作
}
public interface IRepository {
T GetById(int id);
IEnumerable GetAll();
void Add(T entity);
void Remove(T entity);
}
public abstract class RepositoryBase : IRepository where T : class {
protected readonly DbContext Context;
protected RepositoryBase(DbContext ctx) => Context = Context;
public T GetById(int id) => Context.Set().Find(id);
public IEnumerable GetAll() => Context.Set().ToList();
public void Add(T entity) => Context.Set().Add(entity);
public void Remove(T entity) => Context.Set().Remove(entity);
public abstract void SaveChanges(); // 強制衍生類別決定儲存策略
}
public class UserRepository : RepositoryBase {
public UserRepository(DbContext ctx) : base(ctx) { }
public override void SaveChanges() => Context.SaveChanges();
}
虛擬方法用於**單一繼承體系內的擴展點**;抽象類別用於**建構「半成品」基類,強制子類完成關鍵邏輯**;介面用於**定義跨類別層級的契約,支援多重實作與解耦**。現代 C# 開發傾向 「介面優先,抽象類別輔助共享邏輯」 的組合策略。