C#之繼承

来源:http://www.cnblogs.com/afei-24/archive/2017/04/17/6722417.html
-Advertisement-
Play Games

一.繼承的類型 在面向對象的編程中,有兩種截然不同繼承類型:實現繼承和介面繼承 1.實現繼承和介面繼承 *實現繼承:表示一個類型派生於基類型,它擁有該基類型的所有成員欄位和函數。在實現繼承中,派生類型採用基類型的每個函數的實現代碼,除非在派生類型的定義中指定某個函數的實現代碼。在需要給現有的類型添加 ...


一.繼承的類型
  在面向對象的編程中,有兩種截然不同繼承類型:實現繼承和介面繼承
  1.實現繼承和介面繼承
  *實現繼承:表示一個類型派生於基類型,它擁有該基類型的所有成員欄位和函數。在實現繼承中,派生類型採用基類型的每個函數的實現代碼,除非在派生類型的定義中指定某個函數的實現代碼。在需要給現有的類型添加功能,或許多相關的類型共用一組重要的公共功能時,可以使用這種類型的繼承。
  *介面繼承:表示一個類型只繼承了函數的簽名,沒有繼承任何的代碼。在需要指定該類型具有某些可用的特性時,最好使用這種類型的繼承。
  2.多重繼承
  C#不支持多重繼承,但C#允許類型派生自多個介面————多重介面繼承。這說明,C#類可以派生自另一個類和任意多個介面。更準確的說,因為System.Object是一個公共的基類,所以每個C#(除Object之外)都有一個基類,還可以有任意多個介面。
  3.結構的繼承
  使用結構的一個限制是結構不支持實現繼承,但每個結構都自動派生自System.ValueType。不能編碼實現類型層次的結構,但結構可以實現介面。

二.繼承的實現
  語法:
  class MyDreved:BaseClass
  {

  }
  如果類或結構也派生自介面,則用逗號分隔列表中的基類和介面:
  class MyDreved:BaseClass,IIntenface1,IIntenface2
  {

  }

  如果在類定義中沒有指定基類,C#編譯器就假定System.Object是基類。

  1.虛方法
  把一個基類函數聲明為virtual,就可以在任何派生類中重寫(override)該函數:
  class BaseClass
  {
    public virtual void VirtualMethod()
    {
      //
    }
  }

  也可以把屬性聲明為virtual。對於虛屬性或重寫屬性,語法與非虛屬性相同,但要在定義中添加virtual關鍵字:
  public virtual string Name
  {
    get;set;
  }

  C#中虛函數的概念與標準OOP的概念相同:可以在派生類中重寫虛函數。在調用方法時,會調用該派生類的合適方法。在C#中,函數預設情況下不是虛的,但(除了構造函數)可以顯式的聲明為virtual。
  在派生類中重寫一個函數時,要使用override關鍵字顯示聲明:
  class MyDreved: BaseClass
  {
    public override void VirtualMethod()
    {
      //
    }
  }

  成員欄位和靜態函數都不能聲明為virtual,因為這個概念只對類中的實例函數成員有意義。

  2.隱藏方法
  如果簽名相同的方法在基類和派生類中都進行了聲明,但該方法沒有分別聲明為virtual和override,派生類方法就會隱藏基類方法。

class A 
{
    public void a()
    {
      Console.WriteLine('CLASS is A');
    } 
}

class B:A
{
    public void a()
    {
       Console.WriteLine('CLASS is B');
    }
}

class client 
{
    static void main()
    {
        B b=new B();
       A a=b;

       a.a();
          b.a();
    }
}

/*輸出
CLASS IS A
CLASS IS B
*/

 

  在大多數情況下,是要重寫方法,而不是隱藏方法,因為隱藏方法會造成對於給定類的實例調用錯誤的方法。但是,C#語法會在編譯時收到這個潛在錯誤的警告。

  在C#中,要隱藏一個方法應使用new 關鍵字聲明,這樣在編譯時就不會發出警告:
  class A
  {
    public void a()
    {
      Console.WriteLine('CLASS is A');
    }
  }

  class B:A
  {
    public new void a()
    {
       Console.WriteLine('CLASS is B');
    }
  }

  3.調用函數的基類版本
  C#可以從派生類中調用方法的基本版本:base.<MethodName>()
  class MyDreved: BaseClass
  {
    public override void VirtualMethod()
    {
      base.VirtualMethod();
    }
  }
  可以使用base.<MethodName>()語法調用基類中的任何方法,不必從同一方法的重載中調用它。

  4.抽象類和抽象函數
  C#允許把類和函數聲明為abstract.抽象類不能實例化,而抽象不能直接實現,必須在非抽象的派生類中重寫。顯然抽象函數也是虛擬的(儘管不需要提供virtual,實際上,也不能提供該關鍵字)。
  如果類包含抽象函數,則該類也是抽象的,也必須聲明為抽象的:
  abstract class Building
  {
    public abstract void Cal();
  }

  抽象類中不能聲明非抽象方法,但可以聲明其它的非抽象成員。

  5.密封類和密封方法
  C#允許把類和方法聲明為sealed。對於類,這表示不能繼承該類;對於方法,表示不能重寫該方法。
  sealed class A
  {

  }

  class B:A //報錯
  {

  }

  如果基類上不希望有重寫的方法和屬性,就不要把它聲明為virtual.

  6.派生類的構造函數
  假定沒有為任何類定義任何顯示的構造函數,編譯器就會為所有的類提供預設的初始化構造函數,在後臺編譯器可以很好的解決類的層次結構中的問題,每個類中的每個欄位都會初始化為對應的預設值。
  在創建派生類的實例時,實際上會有多個構造函數起作用。要實例化的類的構造函數本身不能初始化類,還必須調用基類中的構造函數。
  構造函數的調用順序是先調用Object,在按照層次結構調用基類的構造函數,由基類到父類,直到到達要實例化的類為止。在這個過程中,每個構造函數都初始化它自己的類中的欄位。因為最先調用的總是基類的構造函數,所以派生類在執行過程中可以訪問任何基類的成員,因為基類已經構造出來了,其欄位也初始化了。

  *在層次結構中添加無參數的構造函數
    在層次結構中添加一個無參數的構造函數會替換預設的構造函數,所以在執行過程中,會預設調用基類中添加的無參數的構造函數。其它方面不變。
  *在層次結構中添加帶參數的構造函數
  在層次結構中要調用這個帶參數的構造函數,需要在父類的構造函數中顯示調用:

public abstract class GenericCustomer
{
    private string name;

    public GenericCustomer()
    {
        name = "<no name>";
    }

    public GenericCustomer(string name)
    {
        this.name = name;
    }


    public string Name 
    { 
        get {return name;}
        set {name = value;}
    }

}

public class Nevermore60Customer : GenericCustomer
{
    private string referrerName;
    private uint highCostMinutesUsed;

    ublic Nevermore60Customer(string name) : this(name, "            <None>")
    {
    }

    public Nevermore60Customer(string name, string referrerName) : base(name)
    {
        this.referrerName = referrerName;
    }

    public string ReferrerName
    {
        get {return referrerName;}
         set {referrerName = value;}
    }

}    

 

 

 

三. 修飾符
  修飾符可以指定方法的可見性:如public或private,還可以指定一項的本質,如方法是virtual或abstract.
  1.可見性修飾符
  修飾符            應用於                    說明
  public              所有類和成員                任何代碼可以訪問
  protected           類的成員和內嵌類              只有在類內部和派生類中訪問
  internal           所有類和成員                只有在類內部和包含它的程式集中訪問
  private          類的成員和內嵌類              只有在類內部訪問
  protected internal    類的成員和內嵌類              只有在類內部,派生類中和包含它的程式集中訪問

  不能把類定義為protected,private,protected internal,因為這些修飾符對於包含在名稱空間中的類型沒有意義。因此這些修飾符只能應用於成員。但是可以用這些修飾符定義嵌套的類(內嵌類,包含在其它類中的類),因為在這種情況下,類也具有成員的狀態:
  public class OuterClass
  {
    protected class InnerClass
    {

    }
  }

  2.其它修飾符
  修飾符      應用於       說明
  new        函數        隱藏函數
  static      所有成員      靜態
  virtual     函數         成員可以由派生類重寫
  abstract      類,函數      抽象
  override      函數          重寫虛擬和抽象的成員
  sealed      類,方法,屬性       不能繼承和重寫
  extern        僅靜態方法     成員在外部用另一種語言實現

四.介面
  public interface IDisposable
  {
    void Dispose();
  }

  聲明介面在語法上和聲明抽象類完全相同,但不允許提供任何成員的實現方式。抽象類可以提供除方法之外的其它成員的實現方式,比如屬性。
  一般情況下,介面只能包含方法,屬性,索引器和事件的聲明。
  不能實例化介面,介面即不能有構造函數,也不能有欄位。介面定義也不允許包含運算符重載。
  在介面中不允許聲明關於成員的修飾符。介面成員總是公有的,不能聲明為虛擬和靜態。如果需要,在實現的類中聲明。

  實現介面的類必須實現介面的所有成員。
  介面可以彼此繼承,其方式與類的繼承方式相同。


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

-Advertisement-
Play Games
更多相關文章
  • 上篇博文中我們將模擬設備註冊到Azure IoT Hub中:我們得到了設備的唯一標識。 Azure IoT 技術研究系列2-設備註冊到Azure IoT Hub 本文中我們繼續深入研究,設備到雲、雲到設備通信。 1. 在Azure IoT Hub中接收模擬設備的消息 讀取設備到雲消息的Event H ...
  • 1.excel導入 public override string CheckAndImportFile(ref DataTable errorInfoDataTable) { porgressBar.SetProgress(5, "開始上傳文件到伺服器....."); //上傳文件到伺服器 file ...
  • 初學Xamarin ,各種折騰,大概這公司破電腦配置差,老是很多問題。 GitHub 真是個好東西,可以參考別人做的,不過下載來運行不了就各種折騰了,為此我重裝電腦兩次了,反正win10安裝就十幾分鐘的事。 問題一:沒有為此解決方案配置選中要生成的項目 這個問題的原因懶得找,可能是項目解決方案拷貝的 ...
  • (一)在運行期間處理和檢查代碼 自定義特性允許把自定義元數據與程式元素關聯起來。反射是一個普通術語,它描述了在運行過程中檢查和處理程式元素的功能。例如,反射允許完成的任務: 枚舉類型的成員 實例化新對象 執行對象的成員 查找程式集的信息 檢查應用於某種類型的自定義特性 創建和編譯新程式集 (二)自定 ...
  • EF中預設的decimal數據精度為兩位數,當我們資料庫設置的精度大於2時,EF將只會保留到2為精度。 網上找到常見的方法為重寫DbContext的OnModelCreating方法: 但如果數據表多或者Decimal類型欄位多的話,用OnModelCreating的方法將會變得相當冗餘,而且不便管 ...
  • url:是要傳輸的地址 type:傳輸類型POST表單,GET數據頭部 datatype:傳輸數據的類型 data:數據必須是一個“表示JSON對象的字元串”,而不是一個“JSON”對象 原因是jquery會把JSON對象序列化成標準POST的形式,你此處的{ id: id }會變成形好id=3這樣 ...
  • using System.IO; using System.Text; namespace iLIS.Common { /// /// 生成Excel文檔內容 /// 存入工作流 /// public class ExcelDocumentx { private readonly StreamWri... ...
  • 方法一: 1、首先建立一個按鈕,在後臺將調用或處理的內容寫入button_click中; 2、在前臺寫一個js函數,內容為document.getElementById("btn1").click() 或者document.getElementById("btn1").onclick() 3、在前臺 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...