c#抽象类和接口的异同

在 C# 中,抽象类(Abstract Class)接口(Interface) 都是实现多态性的重要机制,用于定义规范并约束子类 / 实现类的行为,但它们在设计目的和使用场景上有显著区别。

一、相同点

  1. 无法实例化 两者都不能直接创建对象,只能作为父类(抽象类)或契约(接口)被继承 / 实现。

    复制代码
    // 错误:无法实例化抽象类
    AbstractClass ac = new AbstractClass(); 
    ​
    // 错误:无法实例化接口
    IInterface itf = new IInterface(); 
  2. 包含未实现的成员 都可以定义需要子类 / 实现类具体实现的方法(抽象方法 / 接口方法)。

  3. 支持多态 子类 / 实现类的对象可以赋值给抽象类 / 接口类型的变量,调用时会执行具体实现。

    复制代码
    // 多态示例
    AbstractClass obj1 = new ConcreteClass(); // 抽象类多态
    IInterface obj2 = new InterfaceImpl();   // 接口多态
    obj1.AbstractMethod(); // 执行子类实现
    obj2.InterfaceMethod(); // 执行实现类方法

二、不同点

特性 抽象类(Abstract Class) 接口(Interface)
关键字 abstract class interface
继承方式 单继承(一个类只能继承一个抽象类) 多实现(一个类可以实现多个接口)
成员类型 可包含抽象成员(无实现)和具体成员(有实现) 只能包含抽象成员(默认无实现,C# 8.0+ 可加默认实现)
访问修饰符 成员可以有 publicprotectedinternal 等修饰符 成员默认 public,不能显式添加其他修饰符
字段 / 属性 可以定义字段、普通属性 不能定义字段,只能定义属性(自动属性,无字段实现)
构造函数 可以有构造函数(供子类调用) 不能有构造函数
方法实现 可以包含有实现的方法(非抽象方法) C# 8.0 前:所有方法无实现;C# 8.0+:可添加默认实现
设计目的 表示 "is-a" 关系(继承层次,共享代码) 表示 "can-do" 关系(功能契约,规范行为)

三、代码示例

1. 抽象类示例
复制代码
// 抽象类:包含抽象方法和具体方法
public abstract class Shape
{
    // 字段(抽象类可定义字段)
    protected string _color;
​
    // 构造函数(抽象类可有构造函数)
    public Shape(string color)
    {
        _color = color;
    }
​
    // 抽象方法(必须由子类实现)
    public abstract double GetArea();
​
    // 具体方法(提供默认实现,子类可重写)
    public virtual void PrintColor()
    {
        Console.WriteLine($"颜色:{_color}");
    }
}
​
// 继承抽象类(单继承)
public class Circle : Shape
{
    private double _radius;
​
    public Circle(string color, double radius) : base(color)
    {
        _radius = radius;
    }
​
    // 实现抽象方法
    public override double GetArea()
    {
        return Math.PI * _radius * _radius;
    }
}
2. 接口示例
复制代码
// 接口:定义行为规范
public interface IMovable
{
    // 接口方法(默认public,无实现)
    void Move();
​
    // C# 8.0+ 可添加默认实现
    void Stop()
    {
        Console.WriteLine("停止移动");
    }
}
​
// 实现接口(可多实现)
public class Car : IMovable
{
    // 必须实现接口的抽象方法
    public void Move()
    {
        Console.WriteLine("汽车行驶中...");
    }
​
    // 可选:重写接口的默认实现
    public void Stop()
    {
        Console.WriteLine("汽车刹车停止");
    }
}

四、使用场景选择

  1. 优先使用抽象类

    • 需要在多个相关类间共享代码(字段、方法实现)。

    • 定义的是 "is-a" 关系(如 ShapeCircleRectangle)。

    • 需要控制成员的访问权限(如 protected 方法供子类调用)。

  2. 优先使用接口

    • 定义不相关类的共同行为(如 IMovable 可被 CarBird 实现)。

    • 需要多继承能力(一个类实现多个接口)。

    • 仅需规范行为,不涉及代码共享(如框架中的回调接口)。

总结

  • 抽象类是 "部分实现" 的基类,强调继承和代码复用,适合构建类的层次结构。

  • 接口是 "纯规范" 的契约,强调行为一致性,适合跨类别的功能定义。

  • 在实际开发中,两者常结合使用(如抽象类实现接口,既提供基础实现又遵循规范)。

相关推荐
特立独行的猫a9 分钟前
C 语言各种指针详解
java·c语言·开发语言
Rewloc1 小时前
Trae CN配置Maven环境
java·maven
彭于晏Yan1 小时前
MyBatis-Plus使用动态表名分表查询
java·开发语言·mybatis
Rotion_深3 小时前
C# 对Bitmap 的一些处理方法,裁剪,压缩,旋转等
图像处理·c#
秋月的私语3 小时前
如何快速将当前的c#工程发布成单文件
android·java·c#
天***88963 小时前
使用python写一个应用程序要求实现微软常用vc++功能排查与安装功能
java
代码充电宝4 小时前
LeetCode 算法题【简单】283. 移动零
java·算法·leetcode·职场和发展
切糕师学AI7 小时前
在 C# 中,如何使 $““ 字符串支持换行
c#
ccccczy_7 小时前
Spring Security 深度解读:JWT 无状态认证与权限控制实现细节
java·spring security·jwt·authentication·authorization·securityfilterchain·onceperrequestfilter
Lin_Aries_04217 小时前
容器化 Tomcat 应用程序
java·linux·运维·docker·容器·tomcat