筆記7 面向對象的三大特性(封裝、繼承、多態),值類型和引用類型,抽象類,接口,委託

特性1:封裝

將類裏面的成員變量和方法進行私有化,如果外界要訪問,向外界提供統一的訪問方法。
基於;訪問修飾符。
優點:減少耦合,防止外界進行修改。
實現方式:
1、編寫public方法進行私有變量或方法的封裝。
2、屬性。

對成員變量的封裝

在這裏插入圖片描述

    public class Person
    {
        private int age;    //privare私有的。
        //變量首選都設爲私有的,如果外界要訪問,就開一個方法。
        public void SetAge(int value)   //外界可以傳入參數value
        {
            if (value > 0 && value < 100)
            {
                age = value;
            }
        }

        public int GetAge()
        {
            return age;
        }
    }

對方法的封裝

在這裏插入圖片描述

    public class Person
    {
        private int age;    //privare私有的。
        //變量首選都設爲私有的,如果外界要訪問,就開一個方法。
      

        //暴露給外界
        public void NewFunc()    //寫一個方法,不寫參數
        {
            Eat(age);
        }

        //內部
        private void Eat(int age)
        {
            Console.WriteLine("我的年齡是" + age);  
            //加號可以將age轉換成字符串類型,然後與前面相加。
        }

特性2:繼承

創建新的類(派生類、子類),可以繼承現有類(基類、父類)的特性,並且還可以進行修改和擴充。
C#是單繼承,C++是多繼承。
單繼承:一個父類可以有多個子類,但父類只有一個。
多繼承:一個父類可以有多個子類,且父類可以有多個。

繼承現有類(基類、父類)的特性

在這裏插入圖片描述

修改現有類特性(子類想更改)

覆蓋(覆寫):未經父類允許(new)

覆蓋(覆寫):把原本的方法(父類的)覆蓋了
在這裏插入圖片描述
父類

    public class LaoWang   //這個類叫LaoWang
    {
        public void Play()     
        {
            Console.WriteLine("我要去喝酒");
        }

子類

 public class XiaoWang : LaoWang
    {
       public XiaoWang()
        {
               
        }

        //覆蓋(覆寫):把原本的方法(父類的)覆蓋了
        //確定不用父類的某個方法,要用自己的,那麼就new
        public new void Play()
        {
            Console.WriteLine("我要玩遊戲");
        }
    }

重寫:獲得父類允許(父類:虛方法virtual、子類override)

重寫:利用virtual和override這一對
在這裏插入圖片描述
父類(虛方法virtual:可以被重寫)

public class LaoWang   //這個類叫LaoWang
    {
        //虛方法:可以被重寫
        public virtual void Eat()      //virtual表示其子類此方法可以重寫
        {
            Console.WriteLine("我喜歡喫青椒");
        }
    }  

子類(override)

 //寫一個子類,即便子類裏什麼也沒寫,它也具有父類的特性。   
    //格式:子類名字:父類名字
    public class XiaoWang : LaoWang
    {
       public XiaoWang()
        {
      
        }

        //重寫:利用virtual和override這一對
        public override void Eat()     //override表示告訴父類,我重寫了這個方法
        {
            Console.WriteLine("我喜歡喫肉");
        }

外圍

    class Program
    {
        static void Main(string[] args)
        {
            XiaoWang xw = new XiaoWang();     //實例化一個xw
            xw.Play();
            xw.Eat();    

            Console.ReadKey();
        }
    }

擴充現有類特性

普通方法(需要在重寫的基礎上進行,利用關鍵詞base)

關鍵詞this表示當前類所產生的對象,關鍵詞base代表我的父類。
在寫我的特性前,利用base調用父類的特性。
子類

        //重寫:利用virtual和override這一對
        public override void Eat()     //override表示告訴父類,我重寫了這個方法
        {
                 //關鍵詞this表示當前類所產生的對象
                 //關鍵詞base代表我的父類
            base.Eat();    //在寫我的特性前,調用父類的特性
            Console.WriteLine("我喜歡喫肉");
            /*外界調用結果:我喜歡喫青椒  
                          我喜歡喫肉
            */
        }

構造方法

調用構造方法時,默認先調用父類的構造方法,之後調用子類的構造方法。

構造方法無參數(不需要利用關鍵詞base)

父類

 //構造方法
        public LaoWang()
        {
            Console.WriteLine("我是老王");
        }

子類

public XiaoWang()    //構造方法
        {
            Console.WriteLine("我是小王");

        }

外界

XiaoWang xw = new XiaoWang();      //new,調用XiaoWang的方法

/*結果:我是老王
       我是小王
*/

構造方法帶參數(有無base)

1、無base:無論子類的構造方法寫成什麼樣,都會調用父類默認的構造方法(不帶參數)。
2、有base,且base有參數:通過base,可以指定調用父類的有相同類型參數的構造方法。
3、有base,但base無參數:調用的便是沒有參數的構造方法。結果和無base一樣。
在這裏插入圖片描述

        XiaoWang xw = new XiaoWang();      //new,調用XiaoWang的方法
        //構造方法可以帶參數
        //“:base(age)”表示先調父類的這個有int類型參數構造方法。把20傳給父輩
        public XiaoWang(int age):base(age)    
        {
            Console.WriteLine("我是小王,今年" + age);
        }

方法的重載(區別於重寫)

方法的重載:寫了一個同名、但不同參數的的方法。
這兩個方法是可以同時存在的。區別在於外界調用的時候,依據參數的個數或者類型,確定調用何種方法。
在這裏插入圖片描述
在這裏插入圖片描述
重寫與重載的區別
重寫,涉及父類與子類的關係。
重載,是當前類裏的關係。

特性3:多態

C#:父類類型可以接收子類對象,以至於調用同樣方法產生不同的結果。
C++:同樣的指針可以指向不同的子類對象。
接口也是實現多態的一種方式。

實例化時,可用父類類型接收

在這裏插入圖片描述

//實例化一個xb
XiaoBai xb = new XiaoBai(); 
//NPC xb = new XiaoBai();
NPC npc1 = xb;

在這裏插入圖片描述
在這裏插入圖片描述

多態的作用

如同概念,創建一個父類類型的數組,接收子類對象,以至於調用同樣方法產生不同的結果。
此處由於xb和cs都是文字,所以“不同結果”沒展示出來。
在這裏插入圖片描述

            //new一個NPC數組。數組裏包含xb和cs。xb和cs是模具內實例化出的兩個變量。
            NPC[] npcs = new NPC[] { xb, cs };
            /*此處,我們不需要知道xb和cs的具體類型的。
             只要知道二者都是一個父類,父類裏面是Say方法,
             通過遍歷,就可以得到二者內容。*/
             //快速遍歷
             foreach (NPC npc in npcs)
            {
                npc.Say();
                //原本調方法是:“名稱()”。此處是“實例名稱.模具裏該方法的名稱()”。
            }

值類型和引用類型的區別

值類型:其餘類型
引用類型:數組、類(別忘了string(數組))、接口、委託
邏輯上將內存分爲兩部分:棧(一個個格子)、堆(剩餘大片區域)。
在這裏插入圖片描述
在這裏插入圖片描述

抽象類(abstract,對應override)

提供了部分功能的實現,不能被實例化的類(不能把它new出來)。除了不能實例化和可能包含抽象方法兩個特點,其餘使用和正常類一樣。
在這裏插入圖片描述
父類

    //抽象類(不能被實例化) 添加關鍵字abstract
    public abstract class NPC
    {
        /*可以包含抽象方法:子類必須實現的方法。
         抽象方法只能包含在抽象類當中。添加關鍵字abstract。*/ 
        public abstract void Say();   
        /*抽象方法是子類必須實現的方法,在本類當中是不允許實現的。
         所以,把原本的{}去掉,直接分號結束。
         {}是方法體,有{}即代表方法實現。*/        
    }

子類

    public class XiaoBai : NPC   //創建XiaoBai,XiaoBai繼承NPC
    {
        //此處,XiaoBai必須把父類不可以實現的方法實現。
        //添加關鍵字override
        public override void Say()    
        {

        }
    }

外界

            /*NPC npc1 = new NPC();
            因爲此處NPC是個抽象類,不能new,只能new XiaoBai()。*/
            //一new XiaoBai(),可以用NPC接收。這是因爲多態性依舊保留。
            NPC npc = new XiaoBai();

接口

接口寫法(interface)

同樣不能被實例化,包含的方法必須在繼承該接口的類上實現。一個類可以繼承多個接口。(c#是單繼承(只有一個父類),所以它通過接口實現了多繼承的問題)
在這裏插入圖片描述

    //創建XiaoBai,XiaoBai繼承NPC。
    //XiaoBai除了是NPC,還是Enemy。在父類後面添加逗號接口名稱。
    public class XiaoBai : NPC, Enemy   
    {
        //此處,XiaoBai必須把父類不可以實現的方法實現。
        //添加關鍵字override
        public override void Say()    
        {

        }

        //必須實現接口裏的方法
        /*通過接口,強制讓XiaoBai實現GetHit(受到攻擊)的方法。
         XiaoBai就變成了敵人,我們就可以攻擊它了。*/
        public void GetHit()   
        {

        }
    }

    //接口  interface
    public interface Enemy
    {
        //接口裏面不能寫變量,只能寫方法。而且方法默認爲public,所以不用寫public。
        void GetHit();   //敵人有個方法是受到攻擊。
        //誰實現了Enemy這個接口,誰就有了Enemy的特性:受到攻擊。
    }

接口可以繼承

在這裏插入圖片描述

    //創建XiaoBai,XiaoBai繼承NPC。
    //XiaoBai除了是NPC,還是Enemy。在父類後面添加逗號接口名稱。
    public class XiaoBai : NPC, Boss   
    {
        //XiaoBai必須把父類不可以實現的方法實現。添加override
        public override void Say()     
        {

        }     
        /*必須實現接口裏的方法。
        注意因爲Boss繼承了Enemy受傷害的方法,自身又有扔技能的方法,所以它其實是有兩個方法!
        所以在實現時,注意要實現兩個方法!*/
        public void GetHit()  
        {

        }
        //必須在實現Boss特有的技能
        public void Skill()
        {

        }
    }
    
    //接口  interface
    public interface Enemy
    {
        void GetHit();   //敵人有個方法是受到攻擊。
    }

    //接口是可以繼承的
    public interface Boss : Enemy    //Boss繼承於Enemy
    {
        void Skill();     //Boss會扔技能
    }

接口也可以實現多態性

在這裏插入圖片描述

委託

第一種寫法(需要new)

在這裏插入圖片描述

    public class Person
    {
        /*創建一個委託類型(關鍵字delegate)。
        要求:存放一個返回值爲void,有一個參數爲int類型的方法,類型爲Func。 
        public delegate void Func(int bbb);

        //通過剛纔創建的委託,聲明一個委託
        public Func func;   

        public Person()   //構造方法
        {
            //委託需要new。在()裏寫上要保存的方法名稱。            
            //func = new Func(Say);   第一種寫法
                 
            func(2);    //作用就是可以直接將委託當方法去用
        }

        public void Say(int a)
        {
            Console.WriteLine("我叫小白");
        }
    }

第二種寫法(利用+=和-=)

        public Person()   //構造方法
        {
            //第二種寫法:
            func += Say;
            func(2);
        }  

這種寫法的好處:
委託可以保存多個方法。如果它保存了多個方法,那麼在執行時,它保存的方法會被依次調用。
在這裏插入圖片描述

委託解決的是回調問題

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章