C#基础篇(06)抽象类与接口详解区别

抽象类是 C# 面向对象编程中的一个重要概念,它介于普通类和接口之间,提供了一种定义部分实现并要求派生类完成其余部分的机制。

一、C# 中的抽象类

抽象类是 C# 面向对象编程中的一个重要概念,它介于普通类和接口之间,提供了一种定义部分实现并要求派生类完成其余部分的机制。

1. 抽象类的基本概念

抽象类是不能被实例化的类,主要用于作为其他类的基类。它通过 abstract 关键字声明:

public abstract class Animal
{// 类成员
}

2. 抽象类的特点

  • 不能被实例化​:不能创建抽象类的对象
  • 可以包含抽象成员​:这些成员必须在派生类中实现
  • 可以包含具体实现​:与接口不同,抽象类可以包含已实现的方法
  • 可以包含字段、属性、方法、事件等​:功能比接口更全面
  • 支持访问修饰符​:可以控制成员的访问级别

3. 抽象成员

抽象类可以包含抽象成员(方法、属性、索引器或事件):

public abstract class Animal
{// 抽象方法(无实现)public abstract void MakeSound();// 抽象属性public abstract string Name { get; set; }
}

派生类必须实现所有抽象成员:

public class Dog : Animal
{public override void MakeSound(){Console.WriteLine("Woof!");}private string _name;public override string Name {get { return _name; }set { _name = value; }}
}

4. 抽象类与具体类的比较

特性抽象类具体类
实例化不能
包含抽象成员可以不能
包含具体实现可以可以
继承要求必须实现所有抽象成员无特殊要求

5. 抽象类与接口的比较

特性抽象类接口
实现部分实现无实现
多继承不支持支持
字段可以包含不能包含
构造函数可以有不能有
访问修饰符支持默认public
版本控制添加新成员可能破坏派生类添加新成员会破坏实现

6. 何时使用抽象类

  • 当多个相关类共享通用功能,但各自又有独特行为时
  • 需要提供一些基础实现,同时要求派生类实现特定功能时
  • 需要包含非公共成员(protected/internal)时
  • 需要定义构造函数、析构函数或静态成员时

7. 抽象类的实际示例

public abstract class Shape
{// 抽象方法 - 必须被派生类实现public abstract double Area();// 具体方法 - 已实现public void Display(){Console.WriteLine($"Area: {Area()}");}// 抽象属性public abstract string Color { get; set; }
}public class Circle : Shape
{public double Radius { get; set; }public override string Color { get; set; }public override double Area(){return Math.PI * Radius * Radius;}
}public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }public override string Color { get; set; }public override double Area(){return Width * Height;}
}

8. 抽象类的进阶用法

8.1 抽象类中的构造函数

public abstract class Vehicle
{protected string _model;protected Vehicle(string model){_model = model;}public abstract void Drive();
}public class Car : Vehicle
{public Car(string model) : base(model) { }public override void Drive(){Console.WriteLine($"Driving {_model}");}
}

8.2 部分实现的模板方法模式

public abstract class DataProcessor
{// 模板方法public void Process(){ReadData();ProcessData();SaveResult();}protected abstract void ReadData();protected abstract void ProcessData();protected virtual void SaveResult(){Console.WriteLine("Default save implementation");}
}

9. 总结

抽象类是 C# 中实现多态和代码重用的强大工具,它:

  • 强制派生类实现特定行为
  • 提供共享的基类实现
  • 比接口更灵活,可以包含状态和行为
  • 适合构建具有层次结构的类家族

正确使用抽象类可以使代码更加清晰、可维护,并减少重复代码。

二、C# 中的接口

接口是 C# 中实现多态和抽象的核心机制之一,它定义了一组相关功能的契约,而不提供具体实现。

1. 接口的基本概念

接口使用 interface 关键字声明:

public interface IAnimal
{void MakeSound();string Name { get; set; }
}

2. 接口的特点

  • 纯契约​:只包含成员声明,不包含实现
  • 多继承​:一个类可以实现多个接口
  • 隐式公开​:所有成员默认是 public 的
  • 不能包含字段​:只能包含方法、属性、事件和索引器
  • 不能有构造函数​:因为不能被实例化
  • 不能包含静态成员​(C# 8.0 前)

3. 接口成员的实现

类通过 : 符号实现接口,并提供具体实现:

public class Dog : IAnimal
{private string _name;public void MakeSound(){Console.WriteLine("Woof!");}public string Name {get { return _name; }set { _name = value; }}
}

4. 显式接口实现

当多个接口有同名成员时,可使用显式实现:

public class Animal : IAnimal, IDisposable
{void IAnimal.MakeSound(){Console.WriteLine("Animal sound");}void IDisposable.Dispose(){Console.WriteLine("Disposing");}
}

5. 接口与抽象类的比较

特性接口抽象类
实现可以有
多继承支持不支持
字段不能有可以有
构造函数不能有可以有
版本控制添加成员会破坏实现更灵活
访问修饰符默认public可控制

6. 接口的默认实现(C# 8.0+)

C# 8.0 引入了接口默认实现:

public interface ILogger
{void Log(string message);// 默认实现void LogError(string error){Log($"Error: {error}");}
}

7. 接口的实际应用示例

7.1 依赖注入

public interface IRepository
{void Save(Customer customer);Customer GetById(int id);
}public class SqlRepository : IRepository
{public void Save(Customer customer) { /* SQL实现 */ }public Customer GetById(int id) { /* SQL实现 */ }
}public class CustomerService
{private readonly IRepository _repository;public CustomerService(IRepository repository){_repository = repository;}public void AddCustomer(Customer customer){_repository.Save(customer);}
}

7.2 策略模式

public interface ISortStrategy
{void Sort(List<int> list);
}public class QuickSort : ISortStrategy
{public void Sort(List<int> list) { /* 快速排序实现 */ }
}public class BubbleSort : ISortStrategy
{public void Sort(List<int> list) { /* 冒泡排序实现 */ }
}public class Sorter
{private ISortStrategy _strategy;public Sorter(ISortStrategy strategy){_strategy = strategy;}public void Sort(List<int> list){_strategy.Sort(list);}
}

8. 接口的高级特性

8.1 接口继承

接口可以继承其他接口:

public interface IReadableRepository
{object GetById(int id);
}public interface IWritableRepository : IReadableRepository
{void Save(object entity);
}

8.2 泛型接口

public interface IRepository<T>
{void Add(T entity);T GetById(int id);IEnumerable<T> GetAll();
}

8.3 协变和逆变接口(C# 4.0+)

// 协变(out)
public interface IEnumerable<out T> { /*...*/ }// 逆变(in)
public interface IComparer<in T> { /*...*/ }

9. 接口的使用场景

  1. 定义跨类别的行为​:如 IDisposable
  2. 实现多继承​:一个类可以实现多个接口
  3. 依赖注入​:通过接口解耦依赖
  4. 单元测试​:通过接口创建Mock对象
  5. 插件架构​:定义扩展点
  6. 策略模式​:定义算法族

10. 接口设计的最佳实践

  1. 单一职责​:每个接口应专注于一个特定功能
  2. 命名规范​:以"I"开头,如 IEnumerable
  3. 避免过大接口​:防止实现类负担过重
  4. 优先组合而非继承​:通过多个小接口组合功能
  5. 考虑向后兼容​:添加新成员可能破坏现有实现

11. 总结

C# 中的接口是:

  • 定义行为契约的强大工具
  • 实现松耦合设计的关键
  • 支持多继承的机制
  • 现代C#中功能不断增强(默认实现等)

正确使用接口可以使代码更加灵活、可测试和可维护,是面向对象设计和架构设计中的重要组成部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87922.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87922.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Python将PDF转换成word、PPT

在现代企业环境中,文档格式的转换是一项普遍且关键的需求。PDF(Portable Document Format)作为一种最终的、通常不可编辑的“打印”状态格式,被广泛用于分发和归档。然而,内容的创建、协作和修改主要在Microsoft Office套件中进行,特别是Word(DOCX)和PowerPoint(PPTX)…

香港风水(原生)林地的逻辑分类器

风水林是香港的原生林地&#xff0c;由于地处偏远、地形崎岖以及当地居民的信仰&#xff0c;这些林地得以保存完好。在香港&#xff0c;我们可以追溯到1924年的航拍图像记录&#xff0c;这些黑白航拍图像已经帮助我们划分和区分了林地、草地和灌木丛。然后&#xff0c;通过二战…

[Swarm] Result对象 | 智能体切换 | Response对象 | muduo review

第5章&#xff1a;结果对象 欢迎回到swarm&#xff01; 在上一章第4章&#xff1a;功能中&#xff0c;我们学习了如何通过定义Python功能赋予智能体技能。我们见证了当AI决策调用时&#xff0c;Swarm框架如何执行这些功能。 当前&#xff0c;我们的功能仅返回简单字符串如&q…

[2-02-02].第04节:环境搭建 - Linux搭建ES集群环境

ElasticSearch学习大纲 一、ES集群规划&#xff1a; 关系型数据库&#xff08;比如Mysql&#xff09;非关系型数据库&#xff08;Elasticsearch&#xff09;非关系型数据库&#xff08;Elasticsearch&#xff09;centos7hadoop103192.168.148.3centos7hadoop104192.168.148.4c…

部署并运行Spike-Driven-Transformer或QKFormer

部署并运行Spike-Driven-Transformer或QKFormer 我将指导你如何部署和运行Spike-Driven-Transformer或QKFormer代码,并在CIFAR-10、CIFAR-100和ImageNet-1K数据集上进行训练和测试。 1. 环境准备 首先需要设置Python环境并安装必要的依赖项: # 创建conda环境(推荐) con…

爬虫-request处理POST

1.概念很少在URL写参数&#xff0c;都在form data里面POST 的主要作用是将客户端的数据提交给服务器。这些数据可以是表单输入、文件内容、JSON 数据、XML 数据等等POST 请求携带的数据放在 HTTP 消息的请求体中。这与 GET 请求形成鲜明对比&#xff1a;GET 请求的数据通常附加…

免U盘一键重装系统

免U盘一键重装系统 简单介绍 详细的看GitHub项目首页 GitHub地址 # 下载脚本 curl -O https://cnb.cool/bin456789/reinstall/-/git/raw/main/reinstall.sh || wget -O reinstall.sh $_ # 重装系统 bash reinstall.sh ubuntu # 重启 rebootPS: 重启过程中, 可能需要手动选择r…

自动化一次通过率

自动化测试中的“一次通过率”&#xff08;First-pass Pass Rate&#xff09;​​ 是指自动化测试脚本在首次执行&#xff08;无人工干预、无重试&#xff09;​时&#xff0c;​成功通过的测试用例数占总执行用例数的百分比。​核心概念解析​​​“一次”的含义​​首次运行​…

111111事件

1.抽取 minio 当做文件对象存储服务器&#xff0c;在上面封装一层api&#xff0c;方便操作。 &#xff08;文件上传&#xff0c;指定路径上传&#xff0c;随机命名上传&#xff0c;前端获取token直接传&#xff0c;适合大对象&#xff0c;图片压缩&#xff09; 2.规范整个java项…

Qt的ui文件的编译和使用

Qt中的ui文件编译的类 要么继承 &#xff0c;要么实例化一个变量个人觉得还是继承好点&#xff0c;这样每次调用控件时&#xff0c;不用都要在控件前加上 ui.1 上面使用的是继承的关系&#xff0c;这样就可以直接使用控件.属性&#xff0c;而不用 ui.控件.树形2 QT中UI文件…

数据结构之树,二叉树,二叉搜索树

一.树1.形状2. 相关概念节点的度&#xff1a;一个节点含有的子树的个数称为该节点的度&#xff1b; 如上图&#xff1a;A的为6叶节点或终端节点&#xff1a;度为0的节点称为叶节点&#xff1b; 如上图&#xff1a;B、C、H、I...等节点为叶节点非终端节点或分支节点&#xff1a;…

LLM微调随记录

【如何把领域文献批量转换为可供模型微调的数据集&#xff1f;】 https://www.bilibili.com/video/BV1y8QpYGE57/?share_sourcecopy_web&vd_source8f9078186b93d9eee26026fd26e8a6ed 几个问题 首先要先搞清楚这几个问题 LLM 训练方法如何选择合适的训练方式如何判断是否…

高效处理大体积Excel文件的Java技术方案解析

高效处理大体积Excel文件的Java技术方案解析 引言 在数据密集型应用中&#xff0c;处理数百MB甚至GB级的Excel文件已成为业务刚需。传统基于DOM模型的Excel解析方式&#xff08;如Apache POI的XSSF&#xff09;在处理大规模数据时存在严重的内存瓶颈。本文将深入探讨Java生态中…

JVM垃圾回收机制深度解析

&#x1f5d1;️ JVM垃圾回收机制深度解析 文章目录&#x1f5d1;️ JVM垃圾回收机制深度解析&#x1f50d; 垃圾判定算法&#x1f522; 引用计数法&#x1f310; 可达性分析算法&#x1f504; 垃圾回收算法&#x1f3f7;️ 标记-清除算法&#x1f4cb; 复制算法&#x1f527; …

Docker:容器化技术的基石与实践指南

在现代软件开发和部署中&#xff0c;Docker 作为一种领先的容器化平台&#xff0c;已经成为了开发人员和运维工程师不可或缺的工具。它不仅简化了应用的部署过程&#xff0c;还提高了应用的可移植性和可扩展性。本文将深入探讨 Docker 的核心概念、基本操作以及如何在实际项目中…

java web7(黑马)

Filter简介概念: Filter 表示过滤器&#xff0c;是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。过滤器可以把对资源的请求拦截下来&#xff0c;从而实现一些特殊的功能。过滤器一般完成一些通用的操作&#xff0c;比如:权限控制、统一编码处理、敏感字符处理等等.快速入…

React-forwardRef-useImperativeHandle

forwardRef 暴露dom节点作用&#xff1a;使用ref暴露DOM节点给父组件案例例如在父组件中想要获取子组件input的输入值&#xff0c;和让input获取焦点父组件import { Button } from antd-mobile import Son from "./components/son"; import { useState,useRef } fro…

Unity 用AI自动开发游戏----Cursor研究(实现一套利用Cursor生成模板快速实现原型的框架)

Unity 快速原型开发框架&#xff08;基于 Cursor AI&#xff09; &#x1f9e9; 框架简介 本框架结合了 AI 编程助手 Cursor 的代码生成能力&#xff0c;构建出一套适用于 Unity 项目的模块化原型开发架构。它旨在极大提升开发效率、降低试错成本&#xff0c;特别适用于快速搭…

D触发器实现2分频verilog及电路

使用D触发器完成2分频电路即通过时钟的上升沿或下降沿到来时进行翻转得到&#xff0c;信号的两个状态所占时间长度相同&#xff0c;因此它的输出时钟的占空比为50%。 D触发器实现2分频的电路图如下所示&#xff1a;通过将D触发器2分频电路级联&#xff0c;可实现输入时钟的2N倍…

UniApp完美对接RuoYi框架开发企业级应用

UniApp完美对接RuoYi框架的完整方案及可开发系统类型&#xff0c;结合企业级实践与开源项目经验整理而成&#xff0c;涵盖技术对接、系统设计及实战案例。 &#x1f527; 一、UniApp与RuoYi对接全流程 1. 后端配置&#xff08;RuoYi-Vue/RuoYi-Cloud&#xff09; 跨域支持 在网…