C# 抽象类与接口

        抽象类接口是C#“封装、继承、多态”三大特性中比较重要的组成部分。抽象类和接口这两种类型用于完全不同的目的。抽象类主要用作对象的基类,贡献某些主要的特性,例如共同的目的和结构。接口则主要是用于类,为这些类去添加不同的方法(行为)。下面分别对它们的概念,代码定义,特点区别,应用场景进行说明。

概念

抽象类概念

        抽象类是一种不能被实例化的类,用于作为其他类的基类。它可以包含抽象方法、非抽象方法、字段、属性等成员,用于定义一种通用的类结构和行为,而具体的实现则留给其派生类来完成。

接口概念

        接口是从抽象类演变而来的,接口是一种定义了一组方法、属性、事件或索引器的规范,用于描述类应该具有的行为和功能。类可以实现一个或多个接口,从而遵循接口定义的规范。

代码定义

抽象类定义

        抽象类在C#中通过abstract关键字来声明。

    internal abstract class Animal{//抽象属性声明不提供属性访问器的实现,它声明该类支持属性,而将访问器实现留给派生类public abstract double height { get; }//普通属性public  double weidth { get; set; }//普通字段public  double age;//抽象方法public abstract void Run();//普通方法public void Eat(){Console.WriteLine("Animal can eat.");}//虚方法,子类继承重写public virtual void Move(){Console.WriteLine("Animal can move.");}}internal class Dog : Animal{private double _height;public override double height{get => _height;}public Dog(){_height = 200;}//抽象方法子类必须重写public override void Run(){Console.WriteLine("Dog can run.");}//虚方法子类可以重写也可单继承public override void Move(){Console.WriteLine("Animal move by leg.");}}void Main(){Dog dog = new Dog();Animal animal = dog;animal.weidth = 50;animal.age = 10;animal.Run();Console.WriteLine($"Dog's age->{dog.age},width->{dog.weidth},height->{dog.height}");Console.ReadLine();}

   运行结果为:

Dog can run.
Dog's age->10,width->50,height->200

接口定义

        接口在C#中通过interface关键字来声明。

    public  interface FlyInterface{//属性string Name { get; }//委托和事件event EventHandler Clicked;void Fly();void Move();}public interface RunInterface{void Run();void Move();}//可以继承多个接口internal class Plane : FlyInterface, RunInterface{public string Name => "Play";public event EventHandler Clicked;/*如果类实现两个接口且两个接口包含具有相同签名的成员,显示接口实现是通过使用接口名称和一个句点命名该类成员来进行实现*/void FlyInterface.Move(){Console.WriteLine("Plane move by fly.");}void RunInterface.Move(){Console.WriteLine("Plane move by run.");}public void Fly(){Console.WriteLine("Plane can Fly.");}public void Run(){Console.WriteLine("Plane can Run.");}}void Main(){Plane plane = new Plane();FlyInterface fly = plane;fly.Fly();fly.Move();RunInterface run = plane;run.Run();run.Move();Console.ReadLine();}

   运行结果为:

Plane can Fly.
Plane move by fly.
Plane can Run.
Plane move by run.

特点区别

抽象类的特点

  • 不能被实例化: 抽象类不能被直接实例化,只能被用作其他类的基类。
  • 可以包含抽象方法: 抽象类中可以包含抽象方法,这些方法只有声明,没有实际实现。抽象方法用于强制派生类实现特定的行为。
  • 可以包含非抽象方法: 抽象类中也可以包含普通的非抽象方法,这些方法可以有默认的实现。
  • 可以包含字段和属性: 抽象类可以包含字段和属性,用于存储数据和提供接口。

接口的特点

  • 只能定义方法、属性、事件和索引器: 接口只能包含成员的声明,而不能包含具体的实现。
  • 不能包含字段: 接口不能包含字段,因为字段是具体的数据存储,而接口只定义行为。
  • 类可以实现多个接口: 一个类可以同时实现多个接口,从而具有多个不同的行为。
  • 类必须实现接口成员: 类实现接口后,必须提供接口中定义的所有成员的实现。

主要区别

  • 他们的派生类只能继承一个基类,即只能直接继承一个抽象类,但可以继承任意多个接口;
  • 抽象类中可以定义成员的实现,但接口中不可以;
  • 抽象类中可以包含字段、构造函数、析构函数、静态成员或常量等,接口中不可以;
  • 抽象类中的成员可以是私有的(只要他们不是抽象的)、受保护的、内部的或受保护的内部成员(受保护的内部成员只能在应用程序的代码或派生类中访问),但接口中的成员必须是公共的。

应用场景

抽象类应用场景

  • 当要定义一个类的通用结构和行为,并为派生类提供一些默认实现时,可以使用抽象类。
  • 当要强制派生类实现特定方法,但不需要强制实现所有方法时,可以将部分方法声明为抽象方法。
  • 当需要为基类提供一些具体的实现,但又希望派生类能够重写这些实现时,可以使用抽象类。

接口应用场景

  • 当需要定义一组方法、属性或事件,以实现不同类的多态性时,可以使用接口。
  • 当需要在不同的类中实现共同的行为,而这些类已经继承了其他类时,可以通过实现接口来避免多重继承带来的问题。
  • 当需要在一个类中实现多个不相关的功能时,可以通过实现多个接口来达到目的。

在选择使用抽象类还是接口时,需要根据具体的情况选择:

  • 如果想要定义一组相关的类,共享一些通用的实现,但又要求派生类实现特定的行为,可以使用抽象类。
  • 如果想要定义一组不相关的类,使它们实现共同的行为,可以使用接口。

补充说明

1、接口可以用于定义事件和委托的契约,使不同类能够统一实现事件和委托的处理

2、C#虚方法和抽象方法的区别

  • 抽象方法是只有方法名称,没有方法体,即没有方法的具体实现,子类必须重写父类抽象方法才能实现具体功能;虚函数有方法名称也也有方法体,但是子类可以覆盖,也可不覆盖。
  • 抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化。
  • 抽象方法只能在抽象类中声明,虚方法不是。
  • 派生类必须重写抽象类中的抽象方法,虚方法则不必要。

参考:

【C# 基础精讲】抽象类与接口_c#抽象类不能被实例化-CSDN博客

C#-抽象类与接口_c# 接口与抽象类-CSDN博客

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

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

相关文章

Order Delivery for WooCommerce电商商城订单一体化交付解决方案

Order Delivery for WooCommerce电商商城订单一体化交付解决方案 Order Delivery for WooCommerce电商商城订单一体化交付解决方案使客户可以在结账过程中轻松选择订单的交付日期和时间。 Order Delivery for WooCommerce电商商城订单一体化交付解决方案 让您的客户以流畅且…

数据库原理及应用·关系数据库设计理论

5.1 数据依赖 5.1.1 关系模式中的函数依赖 函数依赖的概念:设X,Y是关系R的两个属性集合,当任何时刻R中的任意两个元组中的X属性值相同时,则它们的Y属性值也相同,则称X函数决定Y,或Y函数依赖于X,记为X→Y。…

分割时间方法

输入开始时间和结束时间以及时间间隔, 并以数组形式输出其中的时间段 const generateTimeSlots (startHour: number, endHour: number, intervalMinutes: number) > {const slots [];let currentTime new Date().setHours(startHour, 0, 0, 0);const endTime…

redis—String字符串

目录 前言 1.字符串数据类型 2.常见命令 3.典型应用场景 前言 字符串类型是Redis最基础的数据类型,关于字符串需要特别注意: 1)首先Redis中所有的键的类型都是字符串类型,而且其他几种数据结构也都是在字符串类似基础.上构建的,例如列表…

【2024 行人重识别最新进展】ReID3D:首个关注激光雷达行人 ReID 的工作!

【2024 行人重识别最新进展】ReID3D:首个关注激光雷达行人 ReID 的工作! 摘要:数据集:方法模型:多任务预训练:ReID Network: 实验结果:结论: 来源:Arxiv 2023…

图像分割算法

(车载)毫米波雷达的静止“目标”滤除问题 https://blog.csdn.net/xhblair/article/details/130849777 车载与体征/手势检测 毫米波雷达信号处理流程 csdn链接 专利-一种基于FPGA的步进频高分辨近程雷达探测系统和方法与流程 https://www.xjishu.com/zhuanli/52/2022114681…

drf知识--05

两个视图基类 # APIView:之前一直在用---》drf提供的最顶层的父类---》以后所有视图类,都继承自它 # GenericAPIView:继承自APIView--》封装 继承APIView序列化类Response写接口 # urls.py--总路由 from django.contrib import admin from dj…

ElasticSearch 使用映射定义索引结构

动态映射 dynamic 可选值解释true默认值,启用动态映射,新增的字段会添加到映射中runtime查询时动态添加到映射中false禁用动态映射,忽略未知字段strict发现未知字段,抛出异常 显示映射 创建映射 PUT user {"mappings&qu…

Elasticsearch可视化平台Kibana [ES系列] - 第498篇

历史文章(文章累计490) 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 全…

three.js后处理(发光描边OutlinePass描边样式

效果&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"></div>&…

圆通速递查询,圆通速递单号查询,对需要的单号记录进行标记

随着网购的普及&#xff0c;快递服务已经深入到我们生活的方方面面,我们每天都需要处理大量的快递信息,为了更高效地管理这些信息&#xff0c;【快递批量查询高手】应运而生。 所需工具&#xff1a; 一个【快递批量查询高手】软件 圆通速递单号若干 操作步骤&#xff1a; …

不同参数规模大语言模型在不同微调方法下所需要的显存总结

原文来自DataLearnerAI官方网站&#xff1a; 不同参数规模大语言模型在不同微调方法下所需要的显存总结 | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051703254378255 大模型的微调是当前很多人都在做的事情。微调可以让大语言模型适应特定领域的任…

【Qt-发布】

Qt编程指南 ■ Qt版本发布■■■ ■ Qt版本发布 生成Release版本。LordCard.exe.查看windeployqt.exe所在目录。 E:\install\Qt\Qt5.14.2\5.14.2\mingw73_64\bin\windeployqt.exe 如果已经将这个路径设置到环境变量中了&#xff0c;那么在当前操作系统的任意目录下都可以访问 …

【华为OD题库-105】滑动窗口最大值-java

题目 题目描述: 有一个N个整数的数组&#xff0c;和一个长度为M的窗口&#xff0c;窗口从数组内的第一个数开始滑动直到窗口不能滑动为止&#xff0c;每次窗口滑动产生一个窗口和&#xff08;窗口内所有数的和)&#xff0c;求窗口滑动产生的所有窗口和的最大值。 输入描述: 第一…

口算练习题(字符串处理)#洛谷

题目描述 王老师正在教简单算术运算。细心的王老师收集了i道学生经常做错的口算题&#xff0c;并且想整理编写成一份练习。 编排这些题目是一件繁琐的事情&#xff0c;为此他想用计算机程序来提高工作效率。王老师希望尽量减少输入的工作量&#xff0c;比如 58 \texttt{58} 5…

IntelliJ IDEA快捷键及调试

文章目录 一、IntelliJ IDEA 常用快捷键一览表1-IDEA的日常快捷键第1组&#xff1a;通用型第2组&#xff1a;提高编写速度&#xff08;上&#xff09;第3组&#xff1a;提高编写速度&#xff08;下&#xff09;第4组&#xff1a;类结构、查找和查看源码第5组&#xff1a;查找、…

05|提示工程(下):用思维链和思维树提升模型思考质量 ## 什么是 Chain of Thought

05&#xff5c;提示工程&#xff08;下&#xff09;&#xff1a;用思维链和思维树提升模型思考质量 什么是 Chain of Thought CoT 这个概念来源于学术界&#xff0c;是谷歌大脑的 Jason Wei 等人于 2022 年在论文《Chain-of-Thought Prompting Elicits Reasoning in Large La…

R-列表、矩阵、数组转化为向量

目录 一、c()函数 二、unlist()函数 一、c()函数 c()&#xff1a;对应的英文是combine. 当你使用c()函数时&#xff0c;它会将输入的对象连接成一个向量。因此&#xff0c;无论输入是矩阵、数组还是列表&#xff0c;c()函数都会将它们连接成一个简单的向量。因此&#xff…

Linux操作系统—磁盘和文件系统管理实用

1. 硬盘和分区基础&#xff1a; - Linux使用设备文件&#xff08;例如 /dev/sda&#xff09;来表示硬盘。 - 使用fdisk或parted等工具对硬盘进行分区。 # 示例&#xff1a;使用fdisk进行分区 sudo fdisk /dev/sda 2. 查看磁盘信息&#xff1a; - 使用lsblk或fdisk查看系统…

k8s修改/etc/resolve.conf导致容器域名解析失败

问题&#xff1a; 因为用户原因&#xff0c;修改了k8s主机中/etc/resolve.conf的dns地址&#xff0c;产生的现象就是主机可以解析域名&#xff0c;但是pod不能解析域名; 原因&#xff1a; CoreDNS 是 Kubernetes 集群中的默认 DNS 服务器&#xff0c;负责处理集群内的 DNS 解…