C# virtual 和 abstract 詳解

簡介

C# 中,virtualabstract 關鍵字都用于面向對象編程中的繼承和多態,它們主要用于方法、屬性和事件的定義,但在用法上存在一些重要的區別。

virtual 關鍵字

virtual 表示可重寫的方法,但可以提供默認實現,派生類可以選擇是否重寫。

使用規則

  • 只能在類成員(方法、屬性、事件)上使用,不能用于字段。
  • 必須有默認實現,子類可以選擇是否 override 進行重寫。
  • 在基類中調用時,調用的是基類的方法,但如果子類重寫了,則會調用子類的實現(運行時多態)。
  • 不能用于 static 方法,但可以用于屬性和事件。

示例:virtual 方法

using System;class BaseClass
{public virtual void ShowMessage(){Console.WriteLine("基類的 ShowMessage() 方法");}
}class DerivedClass : BaseClass
{public override void ShowMessage(){Console.WriteLine("子類的 ShowMessage() 方法");}
}class Program
{static void Main(){BaseClass obj1 = new BaseClass();obj1.ShowMessage(); // 輸出: 基類的 ShowMessage() 方法DerivedClass obj2 = new DerivedClass();obj2.ShowMessage(); // 輸出: 子類的 ShowMessage() 方法BaseClass obj3 = new DerivedClass();obj3.ShowMessage(); // 輸出: 子類的 ShowMessage() 方法 (運行時多態)}
}

virtual 屬性

class Animal
{public virtual string Name { get; set; } = "Unknown Animal";
}class Dog : Animal
{public override string Name { get; set; } = "Dog";
}class Program
{static void Main(){Animal a = new Dog();Console.WriteLine(a.Name); // 輸出: Dog}
}

abstract 關鍵字

abstract 表示抽象成員,沒有實現,必須在派生類中重寫。它只能出現在 abstract 類中。

使用規則

  • 只能在 abstract 類中使用,不能用于 sealed 類(密封類)。
  • 沒有方法體,子類必須 override 提供具體實現。
  • 抽象方法不能有 private 修飾符,但可以是 protectedpublic
  • 抽象方法在基類中不能有默認實現,必須在子類實現。
  • 抽象類本身不能被實例化,但可以有構造函數。

示例:abstract 方法

using System;abstract class Animal
{public abstract void MakeSound(); // 沒有方法體,子類必須實現
}class Dog : Animal
{public override void MakeSound(){Console.WriteLine("汪汪汪!");}
}class Cat : Animal
{public override void MakeSound(){Console.WriteLine("喵喵喵!");}
}class Program
{static void Main(){Animal dog = new Dog();dog.MakeSound(); // 輸出: 汪汪汪!Animal cat = new Cat();cat.MakeSound(); // 輸出: 喵喵喵!}
}

abstract 屬性

abstract class Animal
{public abstract string Name { get; set; }
}class Dog : Animal
{public override string Name { get; set; } = "Dog";
}class Program
{static void Main(){Animal a = new Dog();Console.WriteLine(a.Name); // 輸出: Dog}
}

virtual vs abstract 的區別

關鍵字virtualabstract
是否有實現有默認實現沒有默認實現,必須在子類實現
是否必須重寫可以重寫,也可以不重寫必須被子類重寫
是否能在非 abstract 類中使用可以只能用于 abstract 類
能否實例化可以實例化基類抽象類不能實例化
適用范圍方法、屬性、事件方法、屬性、事件

什么時候用 virtual,什么時候用 abstract?

virtual

  • 適用于提供默認行為,但允許子類覆蓋的場景。
  • 例如:基類提供 virtual 方法 SaveToDatabase(),子類可以重寫也可以直接使用。

abstract

  • 適用于基類無法提供合理默認實現,必須由子類提供具體實現的情況。
  • 例如:Animal 類的 MakeSound() 方法,每種動物的叫聲都不同,所以必須由子類實現。

綜合示例

using System;abstract class Animal
{public abstract void MakeSound(); // 必須由子類實現public virtual void Sleep(){Console.WriteLine("動物正在睡覺...");}
}class Dog : Animal
{public override void MakeSound(){Console.WriteLine("汪汪汪!");}public override void Sleep(){Console.WriteLine("狗狗正在睡覺...");}
}class Program
{static void Main(){Animal myDog = new Dog();myDog.MakeSound(); // 汪汪汪!myDog.Sleep();     // 狗狗正在睡覺...}
}

virtual 方法如何調用基類方法?

當子類重寫了 virtual 方法后,仍然可以在 override 方法中調用 基類的實現,這在 擴展父類功能 時特別有用。

在子類 override 方法中調用 base 方法

using System;class BaseClass
{public virtual void ShowMessage(){Console.WriteLine("基類的 ShowMessage() 方法");}
}class DerivedClass : BaseClass
{public override void ShowMessage(){base.ShowMessage();  // 先調用基類方法Console.WriteLine("子類的 ShowMessage() 方法");}
}class Program
{static void Main(){DerivedClass obj = new DerivedClass();obj.ShowMessage();}
}

輸出:

基類的 ShowMessage() 方法
子類的 ShowMessage() 方法
  • 這里 base.ShowMessage(); 先執行基類的方法,再執行子類的邏輯。
  • 這種方式避免了完全覆蓋,而是基于已有邏輯做擴展。

abstract 和 interface 的區別

C# 中,abstractinterface 都可以定義必須由子類實現的方法,但它們有一些關鍵區別。

abstractinterface
是否有方法實現不一定,可以有 abstract 也可以 virtualC# 8.0+ 支持默認實現,但大多數情況下沒有
是否可以包含字段可以(非 static)不可以
是否可以有構造函數可以不可以
繼承方式只能繼承一個可以實現多個
abstract class Animal
{public abstract void MakeSound();public virtual void Sleep(){Console.WriteLine("睡覺中...");}
}interface IAnimal
{void MakeSound();void Sleep();
}class Dog : Animal, IAnimal  // 可以同時繼承抽象類和接口
{public override void MakeSound(){Console.WriteLine("汪汪汪!");}public void Sleep(){Console.WriteLine("狗狗正在睡覺...");}
}

abstract class 適用于有共享邏輯的場景,而 interface 適用于不同類之間的通用行為。

virtual 和 abstract 結合使用

在某些情況下,抽象類可以定義 virtual 方法,讓子類選擇是否覆蓋。

abstract class Shape
{public abstract void Draw(); // 必須重寫public virtual void Move(){Console.WriteLine("Shape is moving...");}
}class Circle : Shape
{public override void Draw(){Console.WriteLine("畫一個圓形");}public override void Move(){Console.WriteLine("圓形在移動...");}
}class Program
{static void Main(){Shape shape = new Circle();shape.Draw(); // 畫一個圓形shape.Move(); // 圓形在移動...}
}
  • Draw() 是抽象方法,必須重寫。
  • Move() 是虛方法,子類可以選擇是否重寫。

virtual 和 abstract 在性能上的考慮

C# 中,virtual 方法會在運行時通過虛方法表(VTable) 進行調用,而 abstract 只是提供一個強制實現的約定,子類實現后仍然是 virtual 方法。

普通方法調用(非 virtual

public class MyClass
{public void NormalMethod() { }
}// 直接調用,無額外開銷。

virtual 方法調用

public class MyClass
{public virtual void VirtualMethod() { }
}// 通過 VTable 進行間接調用,可能稍微慢一點(但一般無影響)。

abstract 方法調用

public abstract class MyBaseClass
{public abstract void AbstractMethod();
}public class MyClass : MyBaseClass
{public override void AbstractMethod() { }
}// abstract 方法在子類實現后,仍然是虛方法(virtual),運行時仍然使用 VTable 機制。

sealed 和 override 一起使用

sealed 關鍵字可以阻止子類進一步重寫 virtual 方法。

class Parent
{public virtual void Show(){Console.WriteLine("父類方法");}
}class Child : Parent
{public sealed override void Show(){Console.WriteLine("子類方法,不能再被重寫");}
}class GrandChild : Child
{// 這里會報錯,因為 `Show` 方法被 `sealed` 了// public override void Show() { }
}
  • 子類 Child 已經 sealed override,所以 GrandChild 不能再重寫 Show() 方法。

  • 適用于限制特定方法的繼承,比如框架設計時控制擴展性。

什么時候用 virtual,什么時候用 abstract?

virtual

  • 當希望提供一個默認實現,但允許子類根據需要重寫時。

abstract

  • 當基類無法提供默認實現,必須要求子類強制實現時。

sealed override

  • 當希望限制某個方法的進一步重寫時。

用 abstract + virtual 組合

  • 適用于部分方法必須實現,部分方法可以選擇重寫的情況。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/78779.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/78779.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/78779.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自動駕駛的數據集以及yolov8和yolop

項目背景 網絡全部是分割了沒有檢測。 自動駕駛的車道線和可行駛區域在數據集中的表示 自動駕駛系統中的車道線和可行駛區域的表示方式主要有以下幾種: 基于幾何模型:使用幾何模型來描述車道線和可行駛區域的形狀和位置,例如直線、曲線、多…

Oracle DROP、TRUNCATE 和 DELETE 原理

在 Oracle 11g 中,DROP、TRUNCATE 和 DELETE 是三種不同的數據清理操作,它們的底層原理和適用場景有顯著差異 1. DELETE 的原理 類型:DML(數據操作語言) 功能:逐行刪除表中符合條件的數據,保留…

PCIe 5.0光學SSD原型問世!

近日,Kioxia Corporation(鎧俠)、AIO Core Co., Ltd. 和 Kyocera Corporation(京瓷)聯合宣布成功開發了一款支持 PCIe 5.0 接口的光學 SSD 原型。該技術旨在通過光接口替換傳統的電接口,從而顯著增加計算設…

SQL 查詢中涉及的表及其作用說明

SQL 查詢中涉及的表及其作用說明: 涉及的數據庫表 表名別名/用途關聯關系dbo.s_orderSO(主表)存儲訂單主信息(訂單號、日期、客戶等)dbo.s_orderdetailSoD(訂單明細)通過 billid SO.billid 關…

C++學習之金融類安全傳輸平臺項目git

目錄 1.知識點概述 2.版本控制工具作用 3.git和SVN 4.git介紹 5.git安裝 6.工作區 暫存區 版本庫概念 7.本地文件添加到暫存區和提交到版本庫 8.文件的修改和還原 9.查看提交的歷史版本信息 10.版本差異比較 11.刪除文件 12.本地版本管理設置忽略目錄 13.遠程git倉…

【HCIP】GRE VPN實驗筆記

一、實驗拓撲 二、實驗要求 1、按照圖示配置IP地址 2、在R1和R3上配置默認路由使公網區域互通 3、在R1和R3上配置GRE VPN,使兩端私網能夠互相訪問,Tunnel口IP地址如圖 4、在R1和R3上配置RIPv2或者ospf或者靜態,來傳遞兩端私網路由 三、實…

大模型——Llama Stack快速入門 部署構建AI大模型指南

Llama Stack快速入門 部署構建AI大模型指南 介紹 Llama Stack 是一組標準化和有主見的接口,用于如何構建規范的工具鏈組件(微調、合成數據生成)和代理應用程序。我們希望這些接口能夠在整個生態系統中得到采用,這將有助于更輕松地實現互操作性。 Llama Stack 定義并標準化…

ALOPS智能化運維管理平臺

AIOps(Artificial Intelligence for IT Operations)即智能運維,是將人工智能技術應用于 IT 運維管理領域,以實現自動化、智能化的運維決策和管理。以下是關于 AIOps 的詳細介紹: 核心能力 數據收集與整合&#xff1a…

C語言超詳細指針知識(二)

在上一篇有關指針的博客中,我們介紹了指針的基礎知識,如:內存與地址,解引用操作符,野指針等,今天我們將更加深入的學習指針的其他知識。 1.指針的使用和傳址調用 1.1strlen的模擬實現 庫函數strlen的功能是…

一種替代DOORS在WORD中進行需求管理的方法 (二)

一、前景 參考: 一種替代DOORS在WORD中進行需求管理的方法(基于WORD插件的應用)_doors aspice-CSDN博客 二、界面和資源 WORD2013/WORD2016 插件 【已使用該工具通過第三方功能安全產品認證】: 1、 核心功能 1、需求編號和跟…

設計模式 Day 6:深入講透觀察者模式(真實場景 + 回調機制 + 高級理解)

觀察者模式(Observer Pattern)是一種設計結構中最實用、最常見的行為模式之一。它的魅力不僅在于簡潔的“一對多”事件推送能力,更在于它的解耦能力、模塊協作設計、實時響應能力。 本篇作為 Day 6,將帶你從理論、底層機制到真實…

文獻總結:AAAI2025-UniV2X-End-to-end autonomous driving through V2X cooperation

UniV2X 一、文章基本信息二、文章背景三、UniV2X框架1. 車路協同自動駕駛問題定義2. 稀疏-密集混合形態數據3. 交叉視圖數據融合(智能體融合)4. 交叉視圖數據融合(車道融合)5. 交叉視圖數據融合(占用融合)6…

2025藍橋杯python A組題解

真捐款去了,好長時間沒練了,感覺腦子和手都不轉悠了。 B F BF BF 賽時都寫假了, G G G 也只寫了爆搜。 題解其實隊友都寫好了,我就粘一下自己的代碼,稍微提點個人的理解水一篇題解 隊友題解 B 思路: 我…

免費送源碼:Java+ssm+MySQL 校園二手書銷售平臺設計與實現 計算機畢業設計原創定制

摘 要 信息化社會內需要與之針對性的信息獲取途徑,但是途徑的擴展基本上為人們所努力的方向,由于站在的角度存在偏差,人們經常能夠獲得不同類型信息,這也是技術最為難以攻克的課題。針對校園二手書銷售平臺等問題,對校…

工業科學級天文相機:跨界融合的高精密成像解決方案

隨著國內科技的快速發展,工業相機領域正悄然興起一場"天文級"的技術革命。這類兼具工業設備可靠性與天文觀測精度的特殊相機,正在半導體制造、天文觀測、空間探測等領域開辟新的應用疆域。其核心技術突破不僅體現在傳感器性能的提升&#xff0…

論文閱讀筆記——Multi-Token Attention

MTA 論文 在 Transformer 中計算注意力權重時,僅依賴單個 Q 和 K 的相似度,無法有效捕捉多標記組合信息。(對于 A、B 兩個詞,單標記注意力需要分別計算兩個詞的注意力分數,再通過后處理定位共同出現的位置或通過多層隱…

301.找出3位偶數

2094. 找出 3 位偶數 - 力扣&#xff08;LeetCode&#xff09; class Solution {List<Integer> resnew ArrayList<>();List<Integer> linew ArrayList<>();public int[] findEvenNumbers(int[] digits) {Arrays.sort(digits);boolean[] numsnew boolea…

【KWDB 創作者計劃】第二卷:開發者實戰篇

?KWDB技術白皮書卷二&#xff1a;開發者實戰篇 ?1. 自然語言到量子查詢的編譯系統 1.1 NL2QSQL翻譯引擎架構 運行時流程圖解&#xff1a; ┌──────────────────────┐ ┌───────────────────┐ ┌─────────────…

前端工程化之新晉打包工具

新晉打包工具 新晉打包工具前端模塊工具的發展歷程分類初版構建工具grunt使用場景 gulp采用管道機制任務化配置與api簡潔 現代打包構建工具基石--webpack基于webpack改進的構建工具rollup 推薦舉例說明package.jsonrollup.config.mjsmy-extract-css-rollup-plugin.mjssrc/index…

ai軟件UI自動化

在AI與UI自動化結合的場景中,通常涉及計算機視覺(CV)、自然語言處理(NLP)和機器學習(ML)等技術。以下是實現AI驅動UI自動化的關鍵方向、工具和步驟: ?一、核心應用場景? ?元素定位增強? ?問題?:傳統工具依賴XPath/CSS選擇器,易因UI變化失效。?AI方案?:CV識別…