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
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...