C#面向對象核心-多態

来源:https://www.cnblogs.com/tanyuyang/archive/2023/03/28/17266518.html
-Advertisement-
Play Games

多態 1 認識多態 1.1 基本概念 多態是同一個行為具有多個不同表現形式或形態的能力,意味著有多重形式。在面向對象編程範式中,多態性往往表現為"一個介面,多個功能"。 在 C# 中,每個類型都是多態的,因為包括用戶定義類型在內的所有類型都繼承自 Object。 多態性分為靜態的和動態多態。在靜態多 ...


多態

1 認識多態

1.1 基本概念

多態是同一個行為具有多個不同表現形式或形態的能力,意味著有多重形式。在面向對象編程範式中,多態性往往表現為"一個介面,多個功能"。

在 C# 中,每個類型都是多態的,因為包括用戶定義類型在內的所有類型都繼承自 Object。

多態性分為靜態的和動態多態。在靜態多態性中,函數的響應是在編譯時發生的。在動態多態性中,函數的響應是在運行時發生的。

  • 靜態多態:函數重載、運算符重載
  • 動態多態:vob(virtual 虛函數,override 重寫,base 父類)、抽象函數、介面

1.2 使用

class GameObject
{
    public string name;
    public GameObject(string name)
    {
        this.name = name;
    }
    //虛函數 可以被子類重寫
    public virtual void Atk()
    {
        Console.WriteLine("游戲對象進行攻擊");
    }
}
class Player : GameObject
{
    public Player(string name) : base(name)//調用父類的構造函數
    {

    }
    //重寫虛函數
    public override void Atk()
    {
        Console.WriteLine("玩家對象進行攻擊");
    }
}
class Monster : GameObject
{
    public Monster(string name) : base(name)
    {

    }
    public override void Atk()
    {
        base.Atk();//base代表父類,可以通過它來保留父類的行為,會調用一次父類的方法
        Console.WriteLine("怪物對象進行攻擊");
    }
}

class Father
{
    public void SpeakName()
    {
        Console.WriteLine("Father的方法");
    }
}
class Son : Father
{
    public new void SpeakName()
    {
        Console.WriteLine("Son的方法");
    }
}

//Main
//用父類取裝載子類的對象時,有兩個同名的方法,會優先調用父類的 多態就用來解決這類問題
Father f = new Son();
f.SpeakName();
(f as Son).SpeakName();

GameObject p = new Player("abc");//虛函數和重寫解決了問題
p.Atk();

GameObject m = new Monster("def");
m.Atk();
/*
輸出:
Father的方法
Son的方法

玩家對象進行攻擊

游戲對象進行攻擊
怪物對象進行攻擊
*/

2 abstract 抽象類和抽象方法

2.1 抽象類

abstract 關鍵字修飾的類。

特點:

  • 不能被實例化
  • 可以包含抽象方法
  • 繼承抽象類必須重寫其抽象方法
abstract class Thing//抽象一類物品
{
    public string name;
    
    //可以在抽象類中寫抽象函數
}
class Water : Thing
{

}

2.2 抽象方法

abstract 修飾的方法,又叫 純虛方法

特點:

  • 只能在抽象類中聲明
  • 沒有方法體
  • 不能是私有的
  • 繼承後必須實現,用override重寫
abstract class Fruits
{
    public string name;

    public virtual void Test()
    {
        //虛方法可以寫邏輯
    }
    public abstract void Bad();//抽象方法
}
class Apple : Fruits
{
    //虛方法在子類中可以選擇是否重寫
    //抽象方法一定要重寫
    public override void Bad()
    {

    }
}

3 介面

3.1 基本概念

關鍵字:interface,介面是行為的抽象規範,是抽象行為的“基類”,各種類通過繼承它來實現對應的行為。

介面聲明規範:

  1. 不包含成員變數
  2. 只包含方法、屬性、索引器、事件
  3. 成員不能被實現
  4. 成員可以不寫訪問修飾符,而且不能是私有的
  5. 介面不能繼承類,但是介面可以繼承另一個介面

介面使用規範:

  1. 類可以繼承多個介面
  2. 類繼承介面後,必須實現介面中所有成員

特點:

  1. 它和類的聲明類似
  2. 介面是用來繼承的
  3. 介面不能被實例化,但可以作為容器來存儲對象

3.2 聲明

/*
interface 介面名
{

}
介面名:I+帕斯卡命名法
*/
interface IFly
{
    void Fly();//方法

    string Name//屬性
    {
        get;
        set;
    }

    int this[int index]//索引
    {
        get;
        set;
    }

    event Action doSomething;//事件
}

3.3 使用

介面用來繼承:

  1. 類可以繼承1個類,n個介面
  2. 繼承了介面後,必須實現其中的內容,而且必須為 public
  3. 實現的介面函數,可以加 visual 再在子類中 override
  4. 介面遵循里氏替換原則
class Animal
{

}
class Tiger : Animal, IFly//繼承類和介面
{
    //實現介面內容
    public void Fly()
    {

    }
    public string Name
    {
        get;
        set;
    }
    public int this[int index]
    {
        get
        {
            return 0;
        }
        set
        {

        }
    }
    public event Action doSomething;
}

3.4 介面繼承介面

  • 介面繼承介面時,不需要實現
  • 類繼承介面後,去實現介面的所有內容
interface IWalk
{
    void Walk();
}

interface IMove : IFly, IWalk
{

}

class Test : IMove//實現所有內容
{
    public int this[int index] 
    { 
        get => throw new NotImplementedException(); set => throw new NotImplementedException(); 
    }

    public string Name 
    { 
        get => throw new NotImplementedException(); set => throw new NotImplementedException(); 
    }

    public event Action doSomething;

    public void Fly()
    {
        throw new NotImplementedException();
    }

    public void Walk()
    {
        throw new NotImplementedException();
    }
}

3.5 顯示實現介面

  • 當一個類繼承兩個介面,但是介面中存在著同名方法時使用
  • 註意:顯示實現介面時,不能寫訪問修飾符
interface IAtk
{
    void Atk();
}
interface ISuperAtk
{
    void Atk();
}

class Player : IAtk, ISuperAtk
{
    //顯示實現介面:介面名.行為名
    void IAtk.Atk()
    {

    }
    void ISuperAtk.Atk()
    {

    }
}

4 sealed 密封方法

4.1 基本概念

  • 密封方法:用 sealed 修飾的重寫函數,讓虛方法或抽象方法不能再被重寫,和 override 一起出現
  • 密封類:用 sealed 修飾的類,讓類不能被繼承

4.2 使用

abstract class Animal
{
    public string name;

    public abstract void Eat();

    public virtual void Speak()
    {
        Console.WriteLine("giao");
    }
}

class Person : Animal
{
    public override void Eat()
    {

    }

    public override void Speak()
    {

    }
}

class WhitePerson : Person
{
    public sealed override void Eat()//不能重寫了
    {
        base.Eat();
    }

    public override void Speak()
    {
        base.Speak();
    }
}

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

-Advertisement-
Play Games
更多相關文章
  • 藍橋杯【答疑】 題目描述 分析 這是一個貪心演算法,要所得的時刻之和最小,而且下一個同學需要等上一個同學結束以後才能進行,因此需要對所耗總時間進行有小到大的排序,總時間相同的同學則對前兩步時間之和有小到大進行排序,最後算出時間之和即可。 代碼 import java.util.Arrays; impo ...
  • 附件用的fastdf上傳和下載的, 本地開發時就沒考慮過多文件上傳就會有併發的問題,比如多個只上傳成功了一個或者上傳了但是文檔內容缺失了,變成0位元組。 呵。。都是一次難忘的經歷。 經過本地模擬大批量的上傳下載, 發現fastdf是在啟動時就初始化了tracker和stroge, 每次調用過他的介面後 ...
  • 一、Jx9 虛擬機的生命周期 載入 Jx9 腳本 jx9_compile() 或 jx9_compile_file(),載入編譯成功後,Jx9 引擎將自動創建一個實例 (jx9_vm) 並且返回指向此虛擬機的指針用於後續調用。 如載入編譯 Jx9 腳本時出現問題,也就是編譯時出錯,可調用jx9_co ...
  • 生產環境,一個簡單的事務方法,提交失敗,報 Global lock wait timeout 偽代碼如下: @GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 30000,lockRetryInternal=3000,l ...
  • PowerPlume是PowerBuilder深度創新的擴展開發框架(免費商用)。 它的三個主要特色是一、原創功能;二、零改動相容(非侵入性);三、極簡介面設計。 ...
  • 記錄人生第一次重裝系統之後的數據恢復過程,包括桌面恢復、常用軟體下載和屬性修改、vscode插件、zotero數據恢復、onenote筆記數據恢復,讓重裝系統的你不用慌。 ...
  • 發文原因 很多初學者都使用 cargo new [project_name] 來創建項目,並直接在 main.rs 文件中實現所有功能。 這樣是不合理的,並不符合我們 cargo 的開發規範。 下麵將簡單的介紹一下 rust project 中的文件結構。 cargo new [project_na ...
  • 其他 1 命名空間 命名空間用來組織和重用代碼的,命名空間就像一個工具包,類就像工具。 1.1 使用 namespace MyGame { class GameObject { } } namespace MyGame//命名空間可以分開寫 { class Player : GameObject { ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...