C#多態性學習,虛方法、抽象方法、介面等用法舉例

来源:https://www.cnblogs.com/letmebaby/archive/2023/03/27/17255211.html
-Advertisement-
Play Games

1. 多態性定義 C#中的多態性是OOP(面向對象編程)的一個基本概念,它允許一個對象在不同情況下表現出不同的行為,以增強代碼的可重用性和靈活性。 根據網上的教程,我們得知C#多態性分為兩類,靜態和動態。但實際上,C#沒有嚴格的靜態和動態多態性的分法。之所以這麼分,還是為了我們便於理解,我們沿用這個 ...


1. 多態性定義

  C#中的多態性是OOP(面向對象編程)的一個基本概念,它允許一個對象在不同情況下表現出不同的行為,以增強代碼的可重用性和靈活性。
  根據網上的教程,我們得知C#多態性分為兩類,靜態和動態。但實際上,C#沒有嚴格的靜態和動態多態性的分法。之所以這麼分,還是為了我們便於理解,我們沿用這個思維來大概分類:

採用函數重載或運算符重載方法的,屬於靜態多態性;
採用虛方法、抽象方法、介面等方式,屬於動態多態性。

拓展:在靜態多態性中,函數的響應是在編譯時發生的。在動態多態性中,函數的響應是在運行時發生的。什麼意思呢?
在靜態語言中,許多多態性的特性可以在編譯時確定,編譯器可以根據數據類型的信息來確定方法的調用方式。
而在動態語言中,數據類型的確定通常是在運行時進行的,這種行為被稱為動態多態性。

2. 函數重載示例

  函數重載是指在同一個類中,定義多個方法,它們的方法名相同,但是參數類型、參數數量、參數順序不同。以下是一個函數重載的例子:

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }
    public float Add(float a, float b)
    {
        return a + b;
    }
    public double Add(double a, double b)
    {
        return a + b;
    }
}

  在這個例子中,Calculator類定義了4個Add()方法,它們的方法名相同但是參數列表不同(分別有2個整型參數、3個整型參數、2個浮點型參數、2個雙精度浮點型參數)。這些方法根據聲明的參數類型和數量而得到不同的簽名,因此構成函數重載,當調用Add()方法時,編譯器會根據參數的類型和數量來選擇正確的方法重載進行調用。

3. 虛方法示例

  虛方法和重寫(override)方法:在父類中聲明一個虛方法,子類可以重寫該方法並實現自己的行為。在運行時,程式根據對象的實際類型調用相應的方法。這種方式也稱為“消除靜態綁定”。
註意事項:虛方法是使用關鍵字 virtual 聲明的。同時繼承類中的重寫虛函數需要聲明關鍵字 override 。下麵是一個示例:

// 定義一個Animal類和其子類
class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("I am an animal.");
    }
}

class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

class Cat : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Meow!");
    }
}

// 示常式序
class Program
{
    static void Main(string[] args)
    {
        Animal[] animals = new Animal[2];
        animals[0] = new Dog();
        animals[1] = new Cat();

        foreach (Animal animal in animals)
        {
            animal.Speak();
        }

        Console.ReadKey();
    }
}

  在這個例子中,Animal類中聲明瞭一個虛方法Speak(),它的子類 Dog 和 Cat 分別對該方法進行了重寫。在Main 方法中,創建了一個 Animal 數組,其中存放了 Dog 和 Cat 的實例。在foreach迴圈中,程式根據實際對象類型調用了不同的Speak()方法,實現了多態性的效果。

小拓展:關鍵字重寫 override 與覆蓋 new 較為容易搞混,有關兩者區別可移步:C#中重寫(override)及覆蓋(new)的區別詳解

4. 抽象方法示例

  抽象方法是在抽象類中定義的,它沒有具體實現的代碼,而只是定義了方法的名稱、參數和返回值類型等信息。抽象方法必須在子類中進行完整的實現,否則子類本身也必須定義為抽象類。使用abstract關鍵字來定義抽象類和抽象方法。
下麵的示例演示瞭如何定義並使用抽象方法:

abstract class Shape 
{
  public abstract double Area(); // 定義抽象方法Area()
}
// 派生類Rectangle繼承抽象類Shape
class Rectangle : Shape  
{
  double width, height;

  public Rectangle(double w, double h) 
  {
    width = w;
    height = h;
  }
  
  public override double Area() // 實現抽象方法Area()
  {
    return width * height;
  }
}

class Triangle : Shape  
{
  double baseValue, height;

  public Triangle(double bv, double h) 
  {
    baseValue = bv;
    height = h;
  }
  
  public override double Area() // 實現抽象方法Area()
  {
    return baseValue * height * 0.5;
  }
}

class Program 
{
  static void Main(string[] args) 
  {
    Rectangle r = new Rectangle(5, 8);
    Console.WriteLine("矩形的面積 = {0}", r.Area());

    Triangle t = new Triangle(5, 8);
    Console.WriteLine("三角形的面積 = {0}", t.Area());
  }
}

  上面的代碼定義了Shape類和兩個派生類Rectangle和Triangle。Shape類中定義了一個抽象方法Area(),併在Rectangle和Triangle中實現了這個抽象方法。在Main方法中,創建了一個Rectangle對象 r 和一個Triangle對象 t,並分別調用它們的Area()方法計算出它們的面積。

5. 介面示例

  C#介面是一種約定,是一個抽象的類型,它定義了一組公共的方法、屬性、索引器和事件,這些成員沒有實現細節和實現代碼,只定義了介面的行為。

5.1 介面語法

定義介面的語法如下:

interface 介面名稱
{
  方法1
  方法2
  屬性1
  索引器1
  事件1
}

其中,方法、屬性、索引器和事件都是介面的成員,它們都沒有實現,只是定義了行為的名稱和參數。

方法定義的語法如下:
返回類型 方法名稱(參數列表);

屬性定義的語法如下:
屬性類型 屬性名稱 { get; set; }

索引器定義的語法如下:
索引器類型 this[索引器參數] { get; set; }

事件定義的語法如下:
event 事件委托類型 事件名稱;

其中,事件委托類型是一個Delegate類型。

5.2 介面使用示例

  定義一個介面之後,可以通過繼承或實現來使用介面。介面的繼承使用“:”符號,需要註意的是,如果一個類實現了一個介面,那麼它必須實現介面中所有的方法和屬性。下麵是介面示例:

interface IShape
{
  double Perimeter();
  double Area();
}

interface ICircle : IShape
{
  double Radius { get; set; }
}

interface IRectangle : IShape
{
  double Width { get; set; }
  double Height { get; set; }
}

class Circle : ICircle
{
  public double Radius { get; set; }

  public double Perimeter()
  {
    return 2 * Math.PI * Radius;
  }

  public double Area()
  {
    return Math.PI * Radius * Radius;
  }
}

class Rectangle : IRectangle
{
  public double Width { get; set; }
  public double Height { get; set; }

  public double Perimeter()
  {
    return 2 * (Width + Height);
  }

  public double Area()
  {
    return Width * Height;
  }
}

class Program
{
  static void Main(string[] args)
  {
    Circle c = new Circle();
    c.Radius = 1;
    Console.WriteLine("Circle:  Perimeter = {0}, Area = {1}", c.Perimeter(), c.Area());

    Rectangle r = new Rectangle();
    r.Width = 2;
    r.Height = 3;
    Console.WriteLine("Rectangle:  Perimeter = {0}, Area = {1}", r.Perimeter(), r.Area());
  }
}

  上面的代碼定義了IShape、ICircle和IRectangle三個介面、以及Circle和Rectangle兩個類。其中,Circle類實現了ICircle介面,Rectangle類實現了IRectangle介面。在Main方法中,創建了一個Circle對象和一個Rectangle對象,並給它們的屬性賦值。然後分別調用了Circle和Rectangle對象的Perimeter()和Area()方法輸出結果。
運行程式,輸出以下結果:

Circle:  Perimeter = 6.28318530717959, Area = 3.14159265358979
Rectangle:  Perimeter = 10, Area = 6

  可以看到,通過使用介面,我們可以很方便地定義出不同的形狀,然後計算出它們的周長和麵積。這就展示了介面在C#編程中的重要地位。

  想必大家看到這裡對於多態性的實現方式已經有了一定的瞭解,不知大家是否發現,這些方式中,抽象方法和虛方法是如此的相似,那麼我們就有了新的疑問:兩者有何區別?使用場景是否有所不同?

在下麵這篇隨筆中,我針對這個問題進行了深入學習:C#中抽象方法與虛方法的區別


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 什麼是 Spdlog 日誌庫 Spdlog 是一個 C++ 的日誌庫,它具有高效、易用、跨平臺等特點。它可以寫入到控制台、文件等輸出目標,支持多種日誌級別、多線程安全等功能,非常適合在 C++ 項目中使用。 Spdlog 日誌庫的歷史和背景 Spdlog 日誌庫最初由 Gabi Melman 開發, ...
  • Sass IT寶庫整理的SASS快速參考備忘單,列出了 SASS 最有用的功能Sass 基礎,為開發人員分享快速參考備忘單。 Sass 是 Syntactically Awesome Stylesheets 的簡寫,是一個最初由 Hampton Catlin 設計並由 Natalie Weizenb ...
  • 內容援引自JavaGuide、嗶哩嗶哩黑馬程式員資料庫從入門到精通,感謝各位大神原創分享 資料庫Mysql 常見的關係型資料庫包括mysql、SQL Server、Oracle、常見的非關係型資料庫Redis、MongDB等。 特點 Mysql開源免費,生態完善,支持事務、高可用(讀寫分離、分庫分表 ...
  • Spdlog 是一個快速、非同步的 C++ 日誌庫,被廣泛應用於 C++ 項目中。在這篇文章中,我們將探討 Spdlog 日誌庫的實現原理。 Spdlog 的結構 Spdlog 由五個主要組件構成:Loggers、Sinks、Formatters、Async Logger 和 Registry。每個組 ...
  • TiDB 基礎使用 TiDB dashboard使用 TiDB Dashboard 是 TiDB 自 4.0 版本起提供的圖形化界面,可用於監控及診斷 TiDB 集群。TiDB Dashboard 內置於 TiDB 的 PD 組件中,無需獨立部署。 集群概況 查看集群整體 QPS 數值、執行耗時、消 ...
  • python中index()、find()方法,具體內容如下: index() 方法檢測字元串中是否包含子字元串 str ,該方法與 python find()方法一樣,只不過如果str不在 string中會報一個異常。影響後面程式執行 index()方法語法:str.index(str, beg= ...
  • 基於.NET Core + Jquery實現文件斷點分片上傳 前言 該項目是基於.NET Core 和 Jquery實現的文件分片上傳,沒有經過測試,因為博主沒有那麼大的文件去測試,目前上傳2G左右的文件是沒有問題的。 使用到的技術 Redis緩存技術 Jquery ajax請求技術 為什麼要用到R ...
  • 1. 重寫和覆蓋的定義 1.1 重寫(override)的定義 在C#中,用override關鍵字來重寫一個父類中的虛方法或抽象方法。override關鍵字用於指示編譯器,我要用派生類中的一個方法,重寫基類中的同名方法。通過重寫基類中的方法,可以實現多態性。有關重寫與虛方法和抽象方法的詳細示例,可移 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...