四大修飾詞語意速查
| 修飾詞 | 用途 | 綁定時機 | 備註 |
virtual | 基底類別允許覆寫 | 執行期 | 不可搭配 static |
override | 衍生類別覆寫虛擬方法 | 執行期 | 必須搭配基底 virtual/abstract/override |
new | 衍生類別隱藏基底非虛擬成員 | 編譯期 | 消除 CS0114 警告 |
sealed override | 封鎖繼承鏈進一步覆寫 | 執行期 | 只能用於虛擬/已覆寫方法 |
abstract | 強制衍生類別實作 | 執行期 | 類別須標記 abstract |
範例 1:new vs override 行為差異
using System;
class Parent {
public void F() { Console.WriteLine("Parent.F"); } // 非虛擬
public virtual void G() { Console.WriteLine("Parent.G"); } // 虛擬
}
class Child : Parent {
new public void F() { Console.WriteLine("Child.F"); } // 隱藏
public override void G() { Console.WriteLine("Child.G"); } // 覆寫
}
class Test {
static void Main() {
Child b = new Child();
Parent a = b; // 向上轉型
a.F(); b.F(); // 編譯期綁定
a.G(); b.G(); // 執行期綁定
}
}
輸出
Parent.F
Child.F
Child.G
Child.G
a.F() 靜態型別為 Parent → 呼叫 Parent.F(new 隱藏僅影響衍生類別靜態型別)。
a.G() 動態型別為 Child → 呼叫 Child.G(多型)。
範例 2:sealed override 封鎖覆寫
// sealed.cs 編譯為 library 供後續繼承測試
using System;
class Parent {
public virtual void F() { Console.WriteLine("Parent.F"); }
public virtual void G() { Console.WriteLine("Parent.G"); }
}
class Child : Parent {
sealed override public void F() { Console.WriteLine("Child.F"); } // 封鎖
override public void G() { Console.WriteLine("Child.G"); }
}
class Grandson : Child {
// override public void F() { } // 編譯錯誤 CS0239:無法覆寫 sealed 方法
override public void G() { Console.WriteLine("Grandson.G"); } // 允許
}
關鍵規則總結
virtual 不能是 static(執行期型別判斷需要實例)。
override 必須配合基底 virtual/abstract/override,不可搭配 static。
new 為編譯期隱藏,不影響多型行為。
sealed override 僅能用於虛擬或已覆寫方法,密封後不可再覆寫。
abstract 方法隱含 virtual,衍生類別必須 override(除非衍生類別也為 abstract)。
實務設計建議
- 預設方法 非虛擬,僅在明確需求時加
virtual(效能與版本控制考量)。
- 覆寫時務必加
override,避免意外隱藏。
- 庫設計者對不應再被覆寫的關鍵邏輯使用
sealed override 保護語意。
- 介面優於抽象基底類別定義契約,保持鬆耦合。