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


相关推荐
小陈phd1 小时前
多模态大模型学习笔记(三十六)—— 扩散模型与可控生成:从AI涂鸦到精准作画的技术革命
人工智能·笔记·学习
雾岛听蓝3 小时前
Qt Widget控件属性详解
开发语言·经验分享·笔记·qt
m0_614619063 小时前
花了一下午学 Git,整理了一份学习笔记
笔记·git·学习
悠哉悠哉愿意4 小时前
【物联网学习笔记】TIM
笔记·单片机·嵌入式硬件·物联网·学习
中屹指纹浏览器4 小时前
2026指纹浏览器技术选型与落地踩坑指南:从需求匹配到风险规避
经验分享·笔记
编程百晓生4 小时前
《SAP FICO系统配置从入门到精通共40篇》021、CO-PC实战笔记:在制品与差异计算,那些年车间里的“账实不符”
服务器·人工智能·笔记·ar·从入门到精通·sap fico·sap fico系统
WYiQIU5 小时前
宇树科技Web前端岗(AI方向),这不算泄题吧......
前端·vue.js·人工智能·笔记·科技·面试·职场和发展
驭渊的小故事6 小时前
Java的类和对象的笔记
笔记
宵时待雨7 小时前
优选算法专题2:滑动窗口
数据结构·c++·笔记·算法
YuanDaima20487 小时前
矩阵基础原理与题目说明
人工智能·笔记·python·学习·线性代数·矩阵