c# 抽象类与接口

51 阅读3分钟

抽象类

抽象类是c#中的一种特殊类,它不能被实例化。主要用于其他类的基类。抽象类的核心目的是定义一组公共组成的成员。并要求派生类实现这些成员的具体行为 使用关键字abstract来定义抽象类或抽象方法

  • 定义:使用abstract关键字修饰类
  • 特点:
    • 不能被实例化
    • 可以包含抽象成员和非抽象成员
    • 用于定义部分实现的基类
//定义一个抽象类
abstract class Animal
{
    //抽象方法
    public abstract void MakeSound();
    //非抽象方法
    public void sleep()
    {
        Console.WriteLine("Zzz...");
    }
}

抽象方法

  • 定义:使用abstract关键字修饰方法
  • 特点:
    • 只有声明,没有实现(没有方法体)
    • 必须在非抽象派生类中重写
    • 只能存在于抽象类中
 abstract class Shape
{
    public abstract double CalculateArea();
}

抽象类的使用

    abstract class Shape
    {
        public abstract double CalculateArea();
    }

    class Circle : Shape 
    {
        public double Radius { get; set; }
        public override double CalculateArea()
        {
            return Math.PI * Radius*Radius;
        }
    }
    class Rectangle : Shape 
    {
        public double width { get; set; }
        public double height { get; set; }
        public override double CalculateArea()
        {
            return width * height;
        }
    }

接口

接口是c#中定义行为契约的引用类型,它指定了一组必须实现的成员,但不提供具体实现,接口定义了一个类能做什么而不是如何做

  1. 接口定义
    • 定义:使用interface关键字
    • 不包含实现(c#8.0起支持默认实现)
    • 接口成员默认public
    • 实现接口的类必须提供所有成员的实现
    • 语法:
  interface IDrawable 
  {
      void Draw();
      string Color { get; set; }
  }
  1. 接口实现
   interface IDrawable 
   {
       void Draw();
       string? Color { get; set; }
   }
   class Circle : IDrawable
   {
       public string? Color { get; set; }
       public void Draw() { Console.WriteLine($"Drawing a {Color} circle"); }
   }
   class Rectangle : IDrawable 
   {
       public string? Color { get; set; }
       public void Draw() { Console.WriteLine($"Drawing a {Color} circle"); }
   }
  1. 为什么需要接口?
    • 多继承 一个类可以实现多个接口
    • 跨类同一行为 不同类实现相同接口
    • 解耦 依赖接口而非具体实现 降低耦合度
    • 插件架构 通过接口定义扩展点
    • 测试驱动开发 使用接口模拟以来

密封类和密封方法

  1. 密封类定义
    • 定义:使用sealed 关键字修饰类
    • 特点:
      • 不能被继承(阻止派生)
      • 可以实例化
      • 常用于安全或性能优化
    • 语法:
  sealed class MyClass 
  {

  }
  //class class a : MyClass { }//报错
  1. 密封方法
  • 定义:使用sealed关键字修饰的虚方法重写
  • 特点:
    • 阻止在派生类中进一步重写该方法
    • 只能用于重写虚方法的方法
  • 语法:
    class MyClass 
    {
        public virtual void doSomething() { }
    }
    class Der:MyClass 
    {
        public sealed override void doSomething()
        {
            //实现
        }
    }
    class Ier : Der
    {
        public override void doSomething() { }//报错此时继承的dosomething是密封的无法再次重写
    }

接口和抽象类的区别

特性​​接口​​抽象类​
​继承​可实现多个接口只能继承一个抽象类
​成员类型​方法、属性、事件、索引器所有类成员(字段、构造函数等)
​实现​只有声明(C#8+支持默认实现)可包含部分实现
​访问修饰符​成员默认public,不能使用其他修饰符可使用各种访问修饰符
​构造函数​不能有构造函数可以有构造函数
​字段​不能包含实例字段(C#8+支持静态字段)可以包含字段
​设计目的​定义行为契约提供部分实现的基类
​版本控制​添加新成员会破坏现有实现添加新方法更安全
​使用场景​跨类统一行为、多继承模拟代码复用、共享实现