c#笔记之接口和抽象类

为什么要有接口和抽象类

开闭原则:

  • 对扩展开放 新增功能、新需求时,可以新增代码、新增类,来扩展原有系统。

  • 对修改关闭 已经写好、测试通过、正在运行的原有代码不要改,尽量不去动老逻辑,避免改出 Bug。

就是要封装确定的开发不确定的;


学习内容:

一、抽象类

1.1一句话定义

  • abstract 修饰的类
  • 不能直接 new 对象
  • 可以包含:普通方法、抽象方法、字段、属性、构造方法
  • 作用:做父类模板,强制子类必须实现某些方法
  • 抽象方法就是没有大括号没有方法要做什么,就是正常声明加了 abstract 修饰

1.2格式

cs 复制代码
// 抽象类
public abstract class Animal
{
    // 普通字段
    public string Name { get; set; }

    // 普通方法(有实现)
    public void Eat()
    {
        Console.WriteLine($"{Name} 在吃东西");
    }

    // 抽象方法:没有方法体,必须加 abstract
    public abstract void Shout();
}

子类必须要实现抽象方法,就是子类必须要override重写抽象方法

cs 复制代码
public class Dog : Animal
{
    // 必须实现抽象方法 Shout()
    public override void Shout()
    {
        Console.WriteLine("汪汪汪");
    }
}

public class Cat : Animal
{
    public override void Shout()
    {
        Console.WriteLine("喵喵喵");
    }
}

1.3推导过程

现在有一个猫和狗都会叫

cs 复制代码
public class Cat
{
    public void Shout()
    {
        Console.WriteLine("喵喵喵");
    }
}
public class Dog
{
    public void Shout()
    {
        Console.WriteLine("汪汪汪");
    }
}

但是很麻烦可以直接建立一个动物类

cs 复制代码
 public class Animal
 {
   public string Name { get; set; }
     public void Shout()
     {
         if(Name =="Cat")
         {
             Console.WriteLine("喵喵喵");
         }
         else if(Name == "Dog")
         {
             Console.WriteLine("汪汪汪");
         }
     }
 }

但是这样如果后面要加别的动物也很麻烦,而且这样也违反了开闭原则,不是新功能也一直在修改原类;这时候就可以使用重写把这个Animal类作为基类,这样加一个动物就重写Shout方法就好了

cs 复制代码
public class Animal //作为基类
{
   public string Name { get; set; }
public void Eat()
    {
        Console.WriteLine("动物吃");
    }
    public virtual void Shout()
    {
        Console.WriteLine("动物叫");
    }
}
public class Cat:Animal
{
    public override void Shout() //重写
    {
        Console.WriteLine("喵喵喵");
    }
}
public class Dog:Animal
{
    public override void Shout() //重写
    {
        Console.WriteLine("汪汪汪");
    }
}

现在Animal这个类一般也不会实例出来用Shout方法了那不如不写具体的方法把方法体删掉;这时候就是抽象方法了就把方法体删掉把virtual换成abstract 来修饰,类就变成了抽象类也要加abstract ,因为是基于重写的只是virtual换了所以派生类重写方法还是要有override;

而且现在派生类如果不重写Shout方法的话就会报错;

cs 复制代码
public abstract class Animal //抽象类
{
   public string Name { get; set; }
public void Eat()
    {
        Console.WriteLine("动物吃");
    }
    public abstract void Shout();//抽象方法
   
}
public class Cat:Animal
{
    public override void Shout()
    {
        Console.WriteLine("喵喵喵");
    }
}
public class Dog:Animal
{
    public override void Shout()
    {
        Console.WriteLine("汪汪汪");
    }
}

而且现在派生类如果不重写Shout方法的话就会报错;

cs 复制代码
public abstract class Animal //抽象类
{
   public string Name { get; set; }
    public abstract void Shout();//抽象方法
   
}
public class Cat:Animal //这样就会报错
{
   
}
public class Dog:Animal
{
    public override void Shout()
    {
        Console.WriteLine("汪汪汪");
    }
}

二、接口

2.1 定义 接口是什么?

接口就是一份 "规矩"、一份 "合同"。 它只规定:必须做什么,不规定怎么做。


接口里只有 "要求",没有 "实现"

比如你跟快递约定:

  • 必须能寄件
  • 必须能查运费

这就是接口

顺丰怎么做、京东怎么做,接口不管。你只要实现了这个接口,就必须按规矩写这两个方法。

注意接口的方法默认是public的因为接口里的所有方法都要被所有的派生类重写所以只能是默认public

2.2格式

用大写i开头 ,interface修饰

cs 复制代码
public interface IExpress
{
    void Send();    // 必须能寄
    decimal GetFee(); // 必须能算运费
}

2.3推导

在抽象类里还有正常的方法和属性;那如果一个抽象类要全是抽象的方法呢

cs 复制代码
public abstract class Animal
{
 public string Name { get; set; }//常规属性

    public void Eat()//常规方法
    {
        Console.WriteLine("动物吃");
    }

    public abstract void Shout();//抽象方法
    
}
   
public class Dog:Animal
{
    public override void Shout()
    {
        Console.WriteLine("汪汪汪");
    }
}

那就是接口了,因为接口可以理解为全是抽象方法的抽象类,所以可知:接口里的方法派生类必须要都要实现;而且这里不需要override了和继承差不多;

cs 复制代码
 interface iAnimal
 {
    void Shout();
     
 }

 public class Dog:iAnimal
 {
     public  void Shout()
     {
         Console.WriteLine("汪汪汪");
     }
 }

2.4 作用

接口的功能用基类继承也可以做到为什么还要有接口呢?

2.4.1. 最核心原因:C# 类只能继承一个父类

现实世界里,一个东西往往有多种身份

  • 人:既是动物 ,又是劳动者 ,还是消费者
  • 手机:既是通讯工具 ,又是相机 ,还是游戏机

但 C# 规定:一个类只能有一个直接父类,不能同时继承好几个类,但是可以继承无限的接口;

2.4.2. 接口代表 "能力",而不是 "种类"

  • 类继承:是什么 (is a)
    • Dog : Animal → 狗 动物
  • 接口实现:能做什么 (can do)
    • Dog : IRunnable → 狗 能跑
    • Ca'r : IRunnable → 车 也能跑

它们不是一家人,但拥有同一种能力,就可以用同一个接口统一调用。有基类又有接口的时候基类要写在前面:

cs 复制代码
class Player : GameObject, IMovable, IAttackable, IHealable//多接口
{
    // 第一个GameObject是基类名字
}

没有基类的时候
class Player : IMovable, IAttackable, IHealable//多接口
{
    
}

三、抽象类继承、普通继承、接口使用

  • 强制子类必须实现方法 → 用 abstract 抽象类
  • 有默认实现,子类可选重写 → 用 普通类 + virtual
  • 多能力、多 "证书",(多个基类 )→ 用 接口

学习时间:

26.03.27


相关推荐
TANGLONG2222 小时前
【C++】继承详解——基类/派生类、作用域、默认函数、菱形继承(超详细)
java·c语言·c++·经验分享·笔记·ajax
木木_王3 小时前
嵌入式学习 | STM32裸板驱动开发(Day01)入门学习笔记(超详细完整版|点灯实验 + 库函数代码 + 原理全解)
linux·驱动开发·笔记·stm32·学习
largecode3 小时前
能不能让座机号码显示“XX公司”那样的认证名称?申请号码认证方法
经验分享·笔记·音视频·课程设计·oneapi·segmentfault·微信开放平台
Hua-Jay4 小时前
OpenCV联合C++/Qt 学习笔记(十七)----凸包检测、直线检测及点集拟合
c++·笔记·qt·opencv·学习·计算机视觉
是喵斯特ya4 小时前
红日内网靶场1环境搭建
笔记
中屹指纹浏览器4 小时前
2026浏览器插件扩展安全风险溯源与环境隔离防护规范
经验分享·笔记
宵时待雨5 小时前
回溯算法专题1:递归
数据结构·c++·笔记·算法·leetcode·深度优先
今儿敲了吗5 小时前
面向对象(三)——设计模式
笔记·设计模式
是喵斯特ya5 小时前
红日内网靶场1渗透笔记
笔记·安全
一只机电自动化菜鸟5 小时前
一建机电备考笔记(34)焊接技术(设备与材料1)(含考频+题型)
笔记·学习·职场和发展·生活·学习方法