C#和数据库高级:继承与多态

发布于:2024-09-19 ⋅ 阅读:(70) ⋅ 点赞:(0)


面向对象编程(OOP)有三个主要特性:

  1. 封装(Encapsulation)
    封装是将数据(属性)和操作数据的方法(函数)绑定在一起,并隐藏内部实现细节的特性。通过封装,可以将对象的内部状态保护起来,只允许通过对象提供的公共接口进行操作,从而提高代码的安全性和可维护性。

  2. 继承(Inheritance)
    继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的重用。子类可以扩展或修改父类的行为,形成一个层次结构。通过继承,可以简化代码并增加系统的可扩展性。

  3. 多态(Polymorphism)
    多态指的是不同的对象对相同的消息(方法调用)做出不同的响应。它允许一个接口以多种形式出现。例如,同一个方法名称在不同的对象中可以有不同的实现。多态提高了系统的灵活性和扩展性。

这三个特性是面向对象编程的核心,帮助开发者设计更为模块化、易维护和可扩展的软件系统。

一、继承的基本使用
继承的概念:

允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的重用。

继承的特点:

继承的顺序不可逆,继承的下级拥有上一级的属性和方法。

为什么使用继承?

解答:最主要的方法是实现代码的复用,举例:有一个猫类和狗类,但是两者都有大量的属性和方法是重复的,所以这个时候可以建一个动物类,让猫类和狗类继承动物类,减少代码的使用。

应继承的步骤和使用要点:

  • 1、抽象的公共部分放到一个特定的类中(父类)
  • 2、其他子类继承父类,就能拥有父类的属性和方法。
  • 3、根据子类的需要,写单独的特征和方法。

具体实现方法:

在子类的后面使用冒号:父类

 class Dog : Animal
 {
     //赛跑
     public void Race()
     {
         Console.WriteLine("下面我给大家表演《狗狗精彩百米跨栏》,请大家鼓掌啊:>");
     }
 }
二、继承的关键字
1、this关键字

this关键字可以访问父类的成员。

2、base关键字

调用父类的构造函数、调用父类的属性和方法。base关键字可以在方法,构造函数和属性的访问器中使用,但是不可以在结构、成员声名中使用。

错误的使用:

 class Dog : Animal
 {     
     public Dog(string name, string color, string kind, string favorite)
         : base(name, color, kind)//调用父类的构造方法
     {
         this.Favorite = favorite;
     }      
     base.Introduce();//在成员声名中使用是无效的
 }

正确的使用:

父类:

    class Animal
    {
        //无参数构造函数
        public Animal() { }
        //3个参数的构造方法
        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; }//喜好
        //自我介绍
        public void Introduce()
        {
            string info = string.Format("我是漂亮的{0},我的名字叫{1},身穿{2}的衣服,我爱吃{3}!", Kind, Name, Color, Favorite);
            Console.WriteLine(info);
        }
    }

子类:

    class Dog : Animal
    {     
        public Dog(string name, string color, string kind, string favorite)
            : base(name, color, kind)//调用父类的构造函数
        {
            this.Favorite = favorite;
        }      
        //赛跑
        public void Race()
        {
            base.Introduce();//调用父类的方法
            Console.WriteLine("下面我给大家表演《狗狗精彩百米跨栏》,请大家鼓掌啊:>");
        }       
    }

如上使用this也可以,但是最好要用base,更好阅读性,base先调用父类的构造函数,然后再调用子类的构造函数,因为创建子类实例的时候会先创建子类所继承的父类。

3、Protected关键字

如果父类中的某个成员函数只允许其子类访问,那么使用Protected关键字

在这里插入图片描述

// 定义子类 Dog 继承自 Animal
public class Dog : Animal
{
    // 子类构造函数
    public Dog(string name) : base(name)
    {
    }
    // 子类的方法,用于调用父类的 protected 方法
    public void DogSpeak()
    {
        // 可以直接访问父类的 protected 成员
        Speak();
    }
}
4、子类调用父类的构造函数的总结:

问题:如果去掉父类的构造函数,并且子类不使用base那么会如何?

隐式调用:如果其他子类的构造函数没有使用base指明调用的父类的那个构造函数时,子类会默认调用父类的无参数构造函数。

显示调用:如果父类没有无参数的构造函数,子类的构造函数必须指明调用父类的那个构造函数。

总之父类要么写一个无参数的默认的构造函数,要么子类指定,不然会报错。

三、继承的特性
继承的传递性:

A是B的父类,B是C的父类,那么C具有A的特性。

继承的单根性:

一个类只能有一个父类。

四、父类和子类的相互转换

给cat和dog分别添加have的方法:

 class Cat : Animal
 {
     public Cat(string name, string color, string kind, string favorite)
         : base(name, color, kind)
     {
         this.Favorite = favorite;
     }
     //吃饭
     public void Have()
     {
         Console.WriteLine("我们要吃香喷喷的烤鱼啦!");
     }
 }
  class Dog : Animal
  {     
      public Dog(string name, string color, string kind, string favorite)
          : base(name, color, kind)
      {
          this.Favorite = favorite;
      }      
      //吃饭
      public void Have()
      {
          Console.WriteLine("我们要吃香喷喷的排骨啦!");
      }
  }

在这里插入图片描述

      static void Main(string[] args)
      {
          //创建一只狗和一只猫
          Cat objCat = new Cat("球球儿", "黄色", "小花猫", "小鱼");
          Dog objDog = new Dog("棒棒", "黑色", "小黑狗", "排骨");
          //将子类对象添加的父类集合
          List<Animal> list = new List<Animal>();
          list.Add(objCat);
          list.Add(objDog);
          //取出子类对象
          foreach (Animal obj in list)
          {
              if (obj is Cat)
                  ((Cat)obj).Have();
              else if (obj is Dog)
                  ((Dog)obj).Have();
          }
          Console.ReadLine();
      }

由于父类不能直接调用子类的方法,所以这种很麻烦,所以我们引出下面的抽象类和抽象方法。