笔记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);
        }  

这种写法的好处:
委托可以保存多个方法。如果它保存了多个方法,那么在执行时,它保存的方法会被依次调用。
在这里插入图片描述

委托解决的是回调问题

在这里插入图片描述

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