(.NET进阶十一)OOP继承/多态

目录

 

一、面向对象核心原则概述

二、继承的基本使用

三、抽象类和抽象方法

四、多态与里氏替换原则

五、is与as操作符

六、虚方法的使用

七、密封类和方法覆盖

八、简单总结


一、面向对象核心原则概述

  1. 单一职责(SRP:Single reponsibility principle)
    1. 针对类的设计而言,对象的单一职责
    2. 不能设计万能类,要按照对象的基本要求,添加的属性、方法,都属于对象的本身
  2. 开-闭原则(OCP:Open Closed Principle)
    1. 使用场景:随需求变化而修改
    2. 开:通过增加类的方法解决需求问题而不是修改原有类,开的是增加
    3. 闭:对以前他人设计的类或模块最好不要轻易修改,闭的是修改
    4. 好处:让需求变化风险可控,让后期维护成本变小
  3. 里氏替换原则(LSP:Liskov Substitution Principle)
    1. 适用场景:使用继承,并希望使用继承实现程序更多的“动态扩展”(多态)
    2. 基本特点:子类可以在任何地方替换它的父类
    3. 使用:一般是说父类作为方法参数,方法返回类型的时候,通常是传递一个子类对象,或者返回一个子类对象
  4. 接口隔离原则(ISP:Interface Segregation Principle)
    1. 含义:接口最小原则
    2. 特点:要求尽量使用职能单一的接口,而不使用职能复杂、全面的接口
    3. 接口内容太多的后果:接口污染,使用和定义困难,维护成本高,重构系统时首先考虑接口细分
  5. 依赖倒置原则(DIP:Dependence Inversion Principle)
    1. 不倒置的情况是什么:UI->BLL->DAL(强依赖)
    2. 原则特点:要求调用者和被调用者都依赖“抽象”,两者没关联,互不影响
    3. 好处:解耦
    4. 实现途径:提前设计接口库,依赖接口编程,也就是调用接口,和实现接口,调用接口的不管实现,实现的不管调用,也可以通过抽象类完成
    5. 具体做法:接口类库、实例方法和构造方法中使用接口作为参数
  6. 迪米特原则(LOD:Law of Demeter)
    1. 面向对象三大特性:封装、继承、多态
    2. 如何理解:尽量最大化的封装,该用private,internal就不用public
    3. 好处:类暴露成员太多,会让调用者痛苦,并且程序的安全性降低;又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解,不和陌生人说话
    4. 具体做法
      1. 类的成员、类本身、尽量降低访问权限
      2. 类的内部成员尽量不要直接暴露,而是使用属性(只读等)
      3. 类的设计,尽量最小化
      4. 类之间的引用,尽量最少

二、继承的基本使用

  1. 继承的特点
    1. 继承顺序的不可逆性:继承是从上往下一次继承,而不可逆序进行
    2. 继承的延续性:在继承顺序中,下一级具备上一级的属性和特性
  2. 继承的必要性
    1. 代码复用,避免重复
    2. 一处更新,处处更新
  3. 继承的使用方法
    1. 抽象公共部分,放在公用类中(父类)
    2. 其他类(子类)只需要继承父类,即可拥有父类特征(属性和方法)
    3. 根据子类的需求添加属于自己的特征和方法
    4. 具体实现:通过冒号实现继承
  4. 父类和子类的概述
    1. 子类继承父类,父类派生子类
    2. 子类又叫派生类,父类叫基类或超类
    3. 子类继承父类成员,又有自己独立的成员
    4. 继承条件:继承需要符合的关系:is-a的关系
  5. 继承中的构造函数
    1. 使用this关键字访问父类成员
      class Animal
      {
          public Animal(){}
          public Animal(string name,string color,string kind)
          {
              this.Color = color;
              this.Name = name;
              this.Kind = kind;
          }
      
          public string Name{get;set;}
          public string Color{get;set;}
          public string Kind{get;set;}
          public string Favorite{get;set;}
      }
      
      
      class Cat:Animal
      {
          //先初始化父类再初始化子类
          public Cat(string name,string color,string kind):base(name,color,kind)
          {
              this.Favorite= favorite;
          }
      }
    2. 继承中的关键字:this,base,protected
    3. 隐式调用:子类的构造函数没有使用base只能调用父类哪个构造函数时,子类默认调用无参构造,此时父类需要提供无参构造
    4. 显示调用:如果父类没有无参构造,子类构造函数必须指明调用父类哪个构造函数
  6. 继承的总结
    1. 传递性,A->B,B->C,C具有A的特性
    2. 单根性,单一继承

三、抽象类和抽象方法

  • 概念与使用要点
    • 使用关键字abstract修饰的类,称为抽象类
    • 抽象类只是用来列举一个类所具有的的行为,不能单独通过创建对象来使用,如Animal animal = new Animal();是错误的
    • 抽象类可以有抽象方法,也可以没有任何抽象方法
    • 抽象类不能是静态的(static)或是密封的(sealed)
    • 在抽象类中使用abstract修饰的方法称为抽象方法
    • 抽象方法必须在抽象类中定义,不能再普通类中使用
    • 抽象方法只是一个方法的声明,不能有任何方法体
    • 抽象方法仅仅表示一个应该具有的行为,具体实现由其子类实现
    • 抽象方法在子类中被实现(重写)必须使用关键字override
    • 子类必须重写父类的所有方法,除非子类本身也是抽象类
      class Animal
      {
          public string Name{get;set;}
          public string Color{get;set;}
          public string Kind{get;set;}
          public string Favorite{get;set;}
      
      
          public void Introduced()
          {
              string info = string.Format("我是{0},穿{1}的衣服,喜欢吃{2}}",Name,Color,Favorite);
              Console.WriteLine(info);
          }
      
          public abstract void Have();
          
      }
      
      
      class Cat:Animal
      {
          public Cat(string name,string color,string kind,string favorite):base(name,color,kind)
          {
              this.favorite = favorite;
          }
          
          public void Dancing()
          {
              Console.WriteLine(".....");
          }
      
          //重写父类方法
          public override Have()
          {
              Console.WriteLine("重写的具体业务逻辑");
          }
      }
      
      abstract class OtherAnimal:Animal
      {
          public OtherAnimal(string name,string color,string kind,string favorite):base(name,color,kind)
      }
      
      static void Main(string[] args)
      {
          Cat objCat = new Cat("球球","黄色","小花猫","小鱼");
          Dog objDog = new Cat("棒棒","黑色","小黑狗","排骨");
      
          List<Animal> list = new List<Animal>();
          list.Add(objCat);
          list.Add(objDog);
          
          foreach(Animal item in list)
          {
              item.Have();
          }
      }
      

       

四、多态与里氏替换原则

  • 多态理解
    • 不同对象,接收相同消息,产生不同行为,称为多态
    • 多态是由虚拟机(CLR)自行决定的
  • 多态实现与应用
    • 使用继承实现多态
      • 父类中必须有抽象方法或虚方法
      • 子类必须重写父类中的抽象方法或虚方法
      • 子类对象必须转换成父类型去使用
      • 多态提高了程序的可扩展性
  • 里氏替换原则
    • 子类的对象能够替换父类
    • 父类对象不能替换子类
    • 父类方法都要在子类中实现或重写

五、is与as操作符

  1. is检查对象是否与指定类型兼容
  2. as用于在兼容的引用类型之间执行转换,转换失败返回null

六、虚方法的使用

  1. 使用场景:需要在父类中提供一个方法,该方法有自己的方法,子类根据自己的需要决定是否重写该方法,而不是必须重写
  2. class Animal
    {
        public string Name{get;set;}
        public string Color{get;set;}
        public string Kind{get;set;}
        public string Favorite{get;set;}
    
    
        public void Introduced()
        {
            string info = string.Format("我是{0},穿{1}的衣服,喜欢吃{2}}",Name,Color,Favorite);
            Console.WriteLine(info);
        }
    
        
        public virtual void Have()
        {
            Console.WriteLine("Animal的Have方法");
        }
    }
    
    
    class Cat:Animal
    {
        public Cat(string name,string color,string kind,string favorite):base(name,color,kind)
        {
            this.favorite = favorite;
        }
        
        public void Dancing()
        {
            Console.WriteLine(".....");
        }
    
        //重写父类方法,重写则调用子类方法,不重写则调用父类方法
        public override Have()
        {
            Console.WriteLine("来自Cat的Have方法");
        }
    }
    
    
    static void Main(string[] args)
    {
        Cat objCat = new Cat("球球","黄色","小花猫","小鱼");
        Dog objDog = new Cat("棒棒","黑色","小黑狗","排骨");
    
        List<Animal> list = new List<Animal>();
        list.Add(objCat);
        list.Add(objDog);
        
        foreach(Animal item in list)
        {
            item.Have();
        }
    }
    
                                            虚方法                                                   抽象方法
    用virtual修饰用abstract
    要有方法体,哪怕只是一个分号不允许使用方法体
    可以被子类override必须被子类override
    除了密封类都可以写只能在抽象类中
    //重写Tostring方法
    class Student
    {
        public int StuId{get;set;}
        public string StuName{get;set;}
        
        //Tostring方法为Object类的虚方法
        public override string Tostring()
        {
            return string.Format("学号={0},姓名={1}",StuId,StuName);
        }
    }
    
    
    
    static void Main(string[] args)
    {
        int a = 100;
        Console.WriteLine(a.Tostring());//值类型已经被系统重写
        
    }

     

七、密封类和方法覆盖

  1. 密封类
    1. 关键字sealed
      1. 当一个类被sealed修饰后,该类不能被继承
      2. sealed对于保护知识产权起到一定作用,一定程度限制了他人的二次开发
        //该类不能作为父类被继承
        sealed class NoveList
        {
            ...........
        }

         

  2. 方法覆盖
    1. 使用new关键字覆盖父类中的同名方法
      class Animal
      {
          public string Name{get;set;}
          public string Color{get;set;}
          public string Kind{get;set;}
          public string Favorite{get;set;}
      
      
          public void Introduced()
          {
              string info = string.Format("我是{0},穿{1}的衣服,喜欢吃{2}}",Name,Color,Favorite);
              Console.WriteLine(info);
          }
      
          
          public virtual void Have()
          {
              Console.WriteLine("Animal的Have方法");
          }
      }
      
      
      
      class Dog:Animal
      {
          //使用new覆盖父类中的Introduced方法
          public new void Introduced()
          {
              string info = string.Format("HI,My name is{0},穿{1}的衣服,喜欢吃{2}}",Name,Color,Favorite);
              Console.WriteLine(info);
          }
          }
      
      }

       

八、简单总结

  • 封装:隐藏内部实现,稳定外部接口->系统安全性
  • 继承:子类继承父类成员,实现代码复用->开发和维护效率
  • 多态:不同子类,对同一消息,做出不同反应->系统扩展性
    • 实现1:父类作为方法参数,作为方法返回值
    • 实现2:接口作为方法参数,接口作为返回值
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值