首页 后端开发 C#.Net教程 C#中的抽象类与接口的详解

C#中的抽象类与接口的详解

Sep 25, 2017 am 11:15 AM
.net 详解

问题出现:

我们在使用C#的抽象类和接口的时候,往往会遇到以下类似的问题,大致归纳如下:

(1)抽象类和接口有什么本质的区别和联系?

(2)什么时候选择使用抽象类,然啥时候使用接口最恰当呢?

(3)在项目中怎样使用才能使得项目更具有可维护性、扩展性?怎样将它和Struct,类紧密的结合,达到最终的双刃剑作用?

解决方案:

这也是我在学习抽象类和接口的时候遇到的问题,从我归纳的这三个问题,不难看出这也许是我们大多数程序员遇到问题的三个阶段,

第一阶段(基础概念):就象问题1一样,这部分人首先需要扫清基础概念的障碍,首先得懂得什么叫抽象类,什么叫接口?

然后了解抽象类和接口之间的区别和联系是什么?当然这可能需要一段时间去理解和实践,毕竟这些概念比较抽象,属于那种摸不着看不到的东西,当然最主要还是多练习,没事的时候做个Demo实例,把它们都使用一遍,在使用的过程中多想想为什么要这样用?这用有什么好处?能不能使用接口呢,如果不能,使用抽象类好处又在哪?这样可以加深对它们的理解,这也是我的一点点经验吧,呵呵!说了这么多,我还是把问题1总结一下,一是方便自己记,二是加深理解吧。

抽象类和接口的概念:其实这些概念在教科书和博客里基本上一大堆,前辈们总结的也很好了,但是可能在通俗、易懂方面有点晦涩难懂,我就翻译一下,加点陕西版的白话文,嘿嘿。

(1)抽象类:提供了一组派生类访问共享基类的公共方法;

抽象类的特性是:(1)抽象类既包括抽象方法,也可以包括方法的实现;(2)抽象类不能被实例化,也不能被密封;(3)抽象类中的抽象方法要么在派生类中实现,要么用派生抽象类继承(抽象派生类可以继承基类抽象方法的),如果要在派生类中实现 基类的抽象方法,必须使用override 修饰符;(4)抽象类属于单继承(这点属于所有类的同性,在这提一下)(5)抽象类是一族群的抽象,类似于 IS-A;

以上我如果说的还不是很清楚,给你个官网的关于抽象类的地址:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract

(2)接口:包含了一组虚方法的抽象类型;

接口的特性是:(1)接口中只包括虚方法的定义,只有声明定义,没有函数实现;(2)接口类中可以包括属性、事件、索引器等,但不能包括字段;(3)接口类属于多继承;(4)继承了接口的类必须全部实现接口的方法;

抽象类和接口的区别和联系:

相同点:(1)都是不能直接实例化,只能通过继承方式去实现;

(2)都是对事物行为和对象的抽象,形成一定的设计模式;

不同点:

(1)接口支持多继承;抽象类不能实现多继承;

(2)接口包括方法、属性、事件、索引器,不能包括字段;抽象类可以包括字段,也可以包括方法的实现;

(3)接口可以支持回调,抽象类不支持回调

(4)接口可以作为值类型和引用类型基类,而抽象类只能作为引用类型的基类;

第二阶段(使用阶段):就象问题2一样,这部分人对基础有了一定的了解,但就是缺乏一定的实践,或许就是做个简单的Demo了事,那么什么时候用抽象类,啥时用接口呢?

分析第二个问题,我提出3点建议:

第一个建议,对基础概念不只是概念的记忆,要多练、多思,然后再多练、再多思,循环几次,直到熟烂于心;

第二个建议,尽量在自己的项目中使用这方面的知识,去使用它,你才能发现问题,解决问题,才会思考;

第三个建议,对自己使用过的抽象类和接口的项目的知识点进行总结和归纳;
      就什么时候使用抽象类和接口,我总结前辈的经验,给出以下几点,仅供参考:

(1)当设计的组件将来有多个版本的时候一般使用抽象类,例如用C#设计数据库DB,刚开始你可能使用的是sql server ,mysql,以后大型的项目可能要使用oracle,DB这种大型的数据库系统,那么我们在设计类的时候就设计一个抽象的基类DB,让它具有                       数据的一些通用的属性和方法,属性:数据库的连接名,版本,数据库类型,数据库的通用方法:Open(),Close()方法等;

(2)当设计的组件同时支持通用的行为动作,可以考虑接口;例如鸟类,人类,车类都可以有声音,这时候可以设计接口,包含叫的函数行为,然后在各个具体的类中实现;

(3)在继承了接口的派生类或接口中,一旦该接口需要增加行为方法是个比较头疼的事情,必须所有的继承都必须实现它的方法,这个时候可以在派生类去实现一个新增的接口,来实现派生类的独特动作,举例说明:

/// <summary>
/// 实现一个爬行动物的动作接口
/// </summary>
interface IAnimalClimb
{
void Climb();
}
/// <summary>
/// 实现一个会叫的动物的动作接口
/// </summary>
interface ICry
{
void Cry();
}
/// <summary>
/// 实现一个动物抽象类
/// </summary>
public abstract class Animal
{
//动物的名字
public string Name { get; set; }
//动物的颜色
public string Color { get; set; }
//动物抽象类的共有方法
public abstract void Sleep();
public abstract void Breathe();
}
/// <summary>
/// 定义鸟类,通用方法是会飞
/// </summary>
public class Bird : Animal,ICry
{
public override void Sleep()
{
Console.WriteLine("Bird派生类继承了基类的Sleep()方法");
}
public override void Breathe()
{
Console.WriteLine("Bird派生类继承了基类的Breathe()方法");
}
//鸟类可以继承统一的接口动作,例如:叫
public void Cry()
{
Console.WriteLine("Bird派生类继承了接口ICry的叫的方法");
}
}
/// <summary>
/// 定义爬行动物类
/// </summary>
public class Snake : Animal, IAnimalClimb
{
public override void Breathe()
{
Console.WriteLine("Snake派生类继承了基类的Sleep()方法");
}
public override void Sleep()
{
Console.WriteLine("Snake派生类继承了基类的Sleep()方法");
}
//爬行动物可以继承统一的接口动物,例如:爬
public void Climb()
{
Console.WriteLine("Snake派生类继承了接口IAnimalClimb的爬的方法");
}
}
登录后复制

以上代码,只是说明问题,比较简单;
第三阶段(优化阶段):就象问题3一样,我们在做一个抽象类或者接口的时候首先考虑的是能用就行,结果就是定义的类或接口比较多,难以维护和扩展,或者就是类之间有交集,那怎么优化继承关系?怎样才能使得程序具有可维护性和扩展性呢?
我个人建议具备以下几个方面方可:
(1)要有扎实的基础知识和深厚的基础功底;
(2)要有一个多问、多思的心;对于抽象类和接口多问问,为什么不使用抽象类而要使用接口?为什么在这个地方使用接口合适?
(3)多看看前辈们是怎么设计接口和类的,这方面的资料网上搜搜不少;
(4)个人建议多看看设计模式这方面的知识,因为他们是前辈在设计时的经验和思想; 

以上是C#中的抽象类与接口的详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Win11管理员权限获取详解 Win11管理员权限获取详解 Mar 08, 2024 pm 03:06 PM

Windows操作系统是全球最流行的操作系统之一,其新版本Win11备受瞩目。在Win11系统中,管理员权限的获取是一个重要的操作,管理员权限可以让用户对系统进行更多的操作和设置。本文将详细介绍在Win11系统中如何获取管理员权限,以及如何有效地管理权限。在Win11系统中,管理员权限分为本地管理员和域管理员两种。本地管理员是指具有对本地计算机的完全管理权限

C++中的众数函数详解 C++中的众数函数详解 Nov 18, 2023 pm 03:08 PM

C++中的众数函数详解在统计学中,众数指的是一组数据中出现次数最多的数值。在C++语言中,我们可以通过编写一个众数函数来找到任意一组数据中的众数。众数函数的实现可以采用多种不同的方法,下面将详细介绍其中两种常用的方法。第一种方法是使用哈希表来统计每个数字出现的次数。首先,我们需要定义一个哈希表,将每个数字作为键,出现次数作为值。然后,对于给定的数据集,我们遍

Oracle SQL中的除法运算详解 Oracle SQL中的除法运算详解 Mar 10, 2024 am 09:51 AM

OracleSQL中的除法运算详解在OracleSQL中,除法运算是一种常见且重要的数学运算操作,用于计算两个数相除的结果。除法在数据库查询中经常用到,因此了解OracleSQL中的除法运算及其用法是数据库开发人员必备的技能之一。本文将详细讨论OracleSQL中除法运算的相关知识,并提供具体的代码示例供读者参考。一、OracleSQL中的除法运算

C++中的取余函数详解 C++中的取余函数详解 Nov 18, 2023 pm 02:41 PM

C++中的取余函数详解在C++中,取余运算符(%)用于计算两个数相除的余数。它是一种二元运算符,其操作数可以是任何整数类型(包括char、short、int、long等),也可以是浮点数类型(如float、double)。取余运算符返回的结果与被除数的符号相同。例如,对于整数的取余运算,我们可以使用以下代码来实现:inta=10;intb=3;

C#的就业前景如何 C#的就业前景如何 Oct 19, 2023 am 11:02 AM

无论您是初学者还是有经验的专业人士,掌握C#将为您的职业发展铺平道路。

PHP模运算符的作用及用法详解 PHP模运算符的作用及用法详解 Mar 19, 2024 pm 04:33 PM

PHP中的模运算符(%)是用来获取两个数值相除的余数的。在本文中,我们将详细讨论模运算符的作用及用法,并提供具体的代码示例来帮助读者更好地理解。1.模运算符的作用在数学中,当我们将一个整数除以另一个整数时,会得到一个商和一个余数。例如,当我们将10除以3时,商为3,余数为1。模运算符就是用来获取这个余数的。2.模运算符的用法在PHP中,使用%符号来表示模

linux系统调用system()函数详解 linux系统调用system()函数详解 Feb 22, 2024 pm 08:21 PM

Linux系统调用system()函数详解系统调用是Linux操作系统中非常重要的一部分,它提供了一种与系统内核进行交互的方式。其中,system()函数是一个常用的系统调用函数之一。本文将详细介绍system()函数的使用方法,并提供相应的代码示例。系统调用的基本概念系统调用是用户程序与操作系统内核交互的一种方式。用户程序通过调用系统调用函数来请求操作系统

分享几个.NET开源的AI和LLM相关项目框架 分享几个.NET开源的AI和LLM相关项目框架 May 06, 2024 pm 04:43 PM

当今人工智能(AI)技术的发展如火如荼,它们在各个领域都展现出了巨大的潜力和影响力。今天大姚给大家分享4个.NET开源的AI模型LLM相关的项目框架,希望能为大家提供一些参考。https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel是一种开源的软件开发工具包(SDK),旨在将大型语言模型(LLM)如OpenAI、Azure

See all articles