深入淺出OOP(四): 多態和繼承(抽象類)

来源:http://www.cnblogs.com/xijianyao/archive/2016/01/11/5122457.html
-Advertisement-
Play Games

在本文中,我們討論OOP中的熱點之一:抽象類。抽象類在各個編程語言中概念是一致的,但是C#稍微有些不一樣。本文中我們會通過代碼來實現抽象類,並一一進行解析。深入理解OOP(一):多態和繼承(初期綁定和編譯時多態)深入理解OOP(二):多態和繼承(繼承)深入理解OOP(三):多態和繼承(動態綁定和運行...


在本文中,我們討論OOP中的熱點之一:抽象類。抽象類在各個編程語言中概念是一致的,但是C#稍微有些不一樣。本文中我們會通過代碼來實現抽象類,並一一進行解析。

 

Abstract Classes

在微軟的MSDN中,對抽象類有如下的定義:

用abstract 關鍵字可定義抽象類,要求其子類必須實現抽象類的函數、屬性等。抽象類不可被實例化。抽象類提供了統一的定義,用於其不同子類直接共用數據、函數。 抽象類也可定義抽象函數。

 


Abstract Classes實戰

在Visual Studio中添加Console程式,並命名為“InheritanceAndPolymorphism”,添加ClassA.cs,添加抽象類ClassA。

 

using System;

namespace InheritanceAndPolymorphism
{
    public abstract class ClassA
    {

    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassA classA = new ClassA();
            Console.ReadKey();
        }
    }
}

 編譯報錯:

Compile time error: Cannot create an instance of the abstract class or interface 'InheritanceAndPolymorphism.ClassA'

結論:無法用new關鍵字來實例化一個抽象類。


Abstract Class的非抽象函數

給抽象類ClassA添加一些非抽象函數的代碼:

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassA classA = new ClassA();
            Console.ReadKey();
        }
    }

編譯,依然報錯。 抽象類無論是否有抽象、非抽象函數,均無法通過new關鍵字來實例化。


Abstract Class作為基類

我們把抽象類作為基類,添加ClassB—使之繼承自ClassA。

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }
    }

    /// <summary>
    /// Derived class.
    /// Class derived from abstract class ClassA
    /// </summary>
    public class ClassB:ClassA
    {
        
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            Console.ReadKey();
        }
    }

編譯的結果:不再報錯。

結論:一個類可以繼承自abstract 修飾的抽象類,且可被new關鍵字初始化。


Abstract Class的非抽象函數聲明

在ClassA中聲明YYY函數--無函數體。

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }

        public void YYY();
    }

    /// <summary>
    /// Derived class.
    /// Class derived from abstract class ClassA.
    /// </summary>
    public class ClassB:ClassA
    {
        
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            Console.ReadKey();
        }
    }

編譯,結果報錯:

Compile time error: 'InheritanceAndPolymorphism.ClassA.YYY()' must declare a body because it is not marked abstract, extern, or partial

結論是需要對YYY添加函數體,或者添加abstract的修飾符。


Abstract Class的抽象函數聲明

在ClassA的YYY前,添加abstract修飾符。

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }

       abstract public void YYY();
    }

    /// <summary>
    /// Derived class.
    /// Class derived from abstract class ClassA.
    /// </summary>
    public class ClassB:ClassA
    {
        
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            Console.ReadKey();
        }
    }

編譯結果,報錯:

Compiler error: 'InheritanceAndPolymorphism.ClassB' does not implement inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY()'

結論:我們在abstract 類中聲明瞭一個abstract 的函數,但是並未在其子類ClassB中實現其內容;當使用new關鍵字初始化ClassB的時候則會報錯----無法使用new關鍵字初始化一個abstract類。


子類繼承實現抽象函數

在子類中添加YYY的實現。

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }

       abstract public void YYY();
    }

    /// <summary>
    /// Derived class.
    /// Class derived from abstract class ClassA.
    /// </summary>
    public class ClassB:ClassA
    {
        public void YYY()
        {
             
        }
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            Console.ReadKey();
        }
    }

編譯結果,報錯:

Compile time error: 'InheritanceAndPolymorphism.ClassB' does not implement inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY()' Compile time warning: 'InheritanceAndPolymorphism.ClassB.YYY()' hides inherited member 'InheritanceAndPolymorphism.ClassA.YYY()'.

結論:要使得子類繼承基類的YYY函數,需要用到override關鍵字,然後才可以用new關鍵字實例化ClassB。


非抽象類的抽象函數

我們再看看這些代碼:

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }

       abstract public void YYY();
    }

    /// <summary>
    /// Derived class.
    /// Class derived from abstract class ClassA.
    /// </summary>
    public class ClassB:ClassA
    {
        public override void YYY()
        {
             
        }
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            Console.ReadKey();
        }
    }

編譯,結果報錯:

Compiler error: 'InheritanceAndPolymorphism.ClassA.YYY()' is abstract but it is contained in non-abstract class 'InheritanceAndPolymorphism.ClassA'

結果分析:聲明abstract的函數,必須同時聲明類為abstract。abstract 的函數不能同時添加static或virtual關鍵字。


抽象基類函數

/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {
            
        }

       abstract public void YYY();
    }

    /// <summary>
    /// Derived class.
    /// Class derived from abstract class ClassA.
    /// </summary>
    public class ClassB:ClassA
    {
        public override void YYY()
        {
             base.YYY();
        }
    }

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            Console.ReadKey();
        }
    }

 編譯,結果報錯:

Compile time error : Cannot call an abstract base member: 'InheritanceAndPolymorphism.ClassA.YYY()'

結果分析:ClassB中無法使用base調用基類的abstract函數--因為其不存在。

 

最後一個問題,可否在抽象類中添加sealed關鍵字,結果是不可以。

抽象類不能添加sealed、static類修飾符的。


結論

通過下麵幾點,歸納一下本文的結論。

  • 無法使用new來實例化abstract 抽象類
  • abstract 抽象類可以有子類,其子類實現抽象方法後,可被new實例化對象
  • 如聲明瞭abstract 的函數,則必須聲明abstract 的類
  • 當override抽象基類,無法修改基類函數的簽名
  • abstract函數,無法同時添加static、virtual關鍵字
  • abstract 類無法被聲明為sealed、static類

 

原文鏈接:Diving in OOP (Day 4): Polymorphism and Inheritance (All About Abstract Classes in C#)

譯文鏈接:http://www.cnblogs.com/powertoolsteam/p/Diving-in-OOP-Day-Polymorphism-and-Inheritance-All.html

 


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

-Advertisement-
Play Games
更多相關文章
  • 原文鏈接http://blog.csdn.net/joyhen/article/details/8500211最近在看委托,然後看到事件,以前一直很模糊,關於事件的觸發者和響應者的關聯。貼一個簡單的例子:1.新建一個類Control.csusingSystem;namespaceEventCompl...
  • 在今天的手機設備世界里,生活的節奏繼續加快,因此訪問你的網站的用戶的耐心也在漸漸失去。同時,我提供了非常多的特性,為了防止你的網站變得過時或者廉價,你必須跟上競爭對手。你想贏得訪問者的喝彩,但訪問者沒有在頁面停留足夠長的時間來載入頁面,不可能對頁面有很深的印象。這裡是導致網站性能緩慢和無法留住用戶的...
  • 1.局部變數的名稱要有意義,儘量用對應的英文命名,比如“用戶姓名”變數,不要用aa bb cc等來命名,而要使用userName。2.不要使用單個字母的變數,如i、n、x等。而要使用index、temp等。用於迴圈迭代的變數例外。3.應該使用Pascal命名法命名方法名、屬性名、類名和命名空間,且方...
  • 好了,前面所有的都是很簡單的例子,現在開始的是大型重構。對於大型重構來說,情況複雜多變,耗時也會很長,前面的簡單重構大多是在一個小時內可以完成,但是對於大型重構來說可能需要幾個月,甚至數年。如果是一個運行中的系統,重構起來只能每天一點點去慢慢重構。(恕我直言,在國內恐怕這樣的公司也很少。所以我們要自...
  • 描述剛剛使用EF,還沒搞明白,遇到下麵問題,記錄一下。都說EF好用,一直也沒用過,以前寫代碼都是ADO.NET,寫起來費時費力還沒什麼大進展,如果能把這些事簡化一下把精力放到邏輯或者更有用的地方豈不是更好。所以想使用EF。Code First,從字面的意思來看是先有代碼後有資料庫,通過Model來創...
  • 參考學習:第一篇:http://www.cnblogs.com/kissdodog/archive/2012/12/15/2819025.html第二篇:http://www.jb51.net/article/50518.htm使用方法: 第一步:先引入jQuery與ajaxFileUpload插....
  • public partial class Form2 : Form { public Form2() { InitializeComponent(); } private Form1 jishiben; ...
  • 目 錄工業物聯網和集成系統解決方案的技術路線... 1前言... 1第一章 系統架構... 31.1 硬體構架圖... 31.2 組件構架圖... 4第二章 技術選型與介紹... 52.1 開發環境... 52.2 數據源... 52.3 數據採集... 52.4 數據上傳服務... 62.5 消息...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...