C#中的两把双刃剑:抽象类和接口

问题出现:

我们在使用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)继承了接口的类必须全部实现接口的方法;

如果想了解官网关于接口的说明,给你一个地址:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interface

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

相同点:(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)个人建议多看看设计模式这方面的知识,因为他们是前辈在设计时的经验和思想;
以上观点和说明,只是代表我个人的意见和建议,如有好的想法,大家可以相互交流,菜鸟会虚心听取大家的意见和建议。

原文地址:http://www.cnblogs.com/djzxjblogs/p/7587735.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

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

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

相关文章

开封游(二)

短暂的永远浪漫&#xff0c;漫长换来不满。人就是这样&#xff0c;第一天是怀着期盼喜悦的心情来的&#xff0c;等到二天&#xff0c;被漫长的行程磨平心境后就再也不想出来旅游了。 总之第二天的心情只能用疲倦来概括。 本来愉悦的心情&#xff0c;而转折点是在吃完海底捞之…

.NetCore之下载文件

本篇将和大家分享的丝.NetCore下载文件&#xff0c;常见的下载有两种&#xff1a;A标签直接指向下载文件地址和post或get请求后台输出文件流的方式&#xff0c;本篇也将围绕这两种来分享&#xff1b;如果对您有好的帮助&#xff0c;请多多支持。允许站点不识别content-type下载…

jeecg-boot中如何修改自定义主题颜色

大家好&#xff0c;我是雄雄。 前言 今天第一次上老丈人家&#xff0c;哈哈哈&#xff0c;有点猝不及防&#xff0c;本来没准备去&#xff0c;结果正好在小区门口碰到&#xff0c;人家让我去&#xff0c;我就把后备箱里面的东西拿下来带着去的。 聊了几个小时&#xff0c;也还…

跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)

1谈一谈.NET 的跨平台终于要写到这一篇了。跨平台的支持可以说是 Office 365 平台在设计伊始就考虑的目标。我在前面的文章已经提到过了&#xff0c;Microsoft Graph 服务针对一些主流的开源平台&#xff08;主要用来做跨平台应用&#xff09;都有支持&#xff0c;例如 python,…

用指针完成函数参数的调用

#include<stdio.h>addUp(int a,int b,int c){ cab;printf("%d\n",c); return c;}main(){int c;addUp(6,5,c);printf("%d",c); }可以在函数中完成数字的加减但是发现无法再主函数中调用&#xff0c;是个初始值22&#xff0c;所有得想个办法将函数的值…

Java 8中Stream API的这些奇技淫巧!你都Get到了吗?

转载自 Java 8中Stream API的这些奇技淫巧&#xff01;你都Get到了吗&#xff1f; Stream简介 Java 8引入了全新的Stream API。这里的Stream和I/O流不同&#xff0c;它更像具有Iterable的集合类&#xff0c;但行为和集合类又有所不同。stream是对集合对象功能的增强&#x…

基于Office 365的随需应变业务应用平台

这是我去年10月底在微软技术大会&#xff08;Microsoft Ignite 2016) 上面的演讲主题&#xff0c;承蒙大家抬爱&#xff0c;也沾了前一场明星讲师的光&#xff0c;我记得会场几乎是满座。观众中既有IT部门的技术人员&#xff0c;也有业务部门的用户&#xff0c;也有少量的开发人…

jeecg中新建接口后报错404的解决方法

大家好&#xff0c;我是雄雄。 前言 最近项目中&#xff0c;一直用的是jeecg-boot的微服务版本&#xff0c;尤其是第一次用微服务&#xff0c;所以在用的过程中&#xff0c;各种问题层出不穷&#xff0c;我们就在边学习边应用的道路上缓缓前进。 索性现在项目已经做的差不多了…

一分钟理解Java公平锁与非公平锁

转载自 一分钟理解Java公平锁与非公平锁 和朋友聊天他提到&#xff1a;ReentrantLock 的构造函数可以传递一个 bool 数据&#xff0c;true 时构造的是“公平锁”、false 时构造的是“非公平锁”。我的印象中锁是不区分类型的&#xff0c;所以认为这应该是 Java 发明的概念&…

为什么你需要将代码迁移到ASP.NET Core 2.0?

随着 .NET Core 2.0 的发布&#xff0c;.NET 开源跨平台迎来了新的时代。开发者们可以选择使用命令行、个人喜好的文本编辑器、Visual Studio 2017 15.3 和 Visual Studio Code 来开发自己的 .NET Core 2.0 项目。同时&#xff0c;微软 .NET 开发工具组也宣布了 ASP.NET Core 2…

typedef用法

#include<stdio.h> typedef struct Student {int age;int score;}St; int main(){St st{200,100};//等价于 struct Student st 直接命名&#xff0c;省略/很多不必要步骤 printf("%d",st.age);}typedef的核心在于指针而不是仅仅简化了结构 #include<stdi…

jeecg-boot中如何放开接口路由

大家好&#xff0c;我是雄雄。 前言 今天是国庆假期的第5天了&#xff0c;7天的时间&#xff0c;感觉过的挺快&#xff0c;前三天都在下雨&#xff0c;后四天降温冻的瑟瑟发抖。 这次假期完事儿了之后就到元旦&#xff0c;春节了&#xff0c;得好好的珍惜。 今天介绍一下&…

nssl1174-阶乘【!基础!数论】

前言 比赛时xjq说这道题很水&#xff0c;是个基础数论。 然后… 就连交都没交 正题 给出n个数&#xff0c;求一个最小的mmm使得 m!∏i1naiq(q∈N)\frac{m!}{\prod_{i1}^na_i}q(q\in N_)∏i1n​ai​m!​q(q∈N​) 解题思路 我们考虑因为要求在一起的乘积&#xff0c;所以个体…

带着小C看动物

大家好&#xff0c;我是雄雄。 整个国庆假期期间&#xff0c;一出门就背着我的小C书包出去。 第一天带着我对象的妈妈去医院检查了下&#xff0c;然后去原来酒店老板那喝羊汤。第二天准备去我对象家的东西&#xff0c;去超市买了一后备箱&#xff0c;晚上就去她家了趟&#xf…

弹性和瞬态故障处理库Polly介绍

前言本节我们来介绍一款强大的库Polly&#xff0c;Polly是一种.NET弹性和瞬态故障处理库&#xff0c;允许我们以非常顺畅和线程安全的方式来执诸如行重试&#xff0c;断路&#xff0c;超时&#xff0c;故障恢复等策略。 Polly针对对.NET 4.0&#xff0c;.NET 4.5和.NET Standar…

一分钟理解Java包装类型

转载自 一分钟理解Java包装类型 Java 一直标榜自己是一个纯粹的面向对象语言&#xff0c;自作聪明的为所有的值类型都提供相应的引用类型&#xff08;不明白这两个概念&#xff0c;看之前的《一分钟理解传值和传引用》&#xff09;比如&#xff1a;int 类型对应的有 Integer&…

SQL Server 2017 正式发布

SQL Server 2017 跨出了重要的一步&#xff0c;它力求通过将 SQL Server 的强大功能引入 Linux、基于 Linux 的 Docker 容器和 Windows&#xff0c;使用户可以在 SQL Server 平台上选择开发语言、数据类型、本地开发或云端开发&#xff0c;以及操作系统开发。微软拥抱开源的脚步…

关于链表的简单创建和遍历

这是网上的的源码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <malloc.h>// 定义链表中的节点 typedef struct node {int member; // 节点中的成员struct node *pNext; // 指向下一个节点的指针 }Node,*…

可能是最全面的 Java G1学习笔记

转载自 可能是最全面的 Java G1学习笔记 引子 最近遇到很多朋友过来咨询G1调优的问题&#xff0c;我自己去年有专门学过一次G1&#xff0c;但是当时只是看了个皮毛&#xff0c;因此自己也有不少问题。总体来讲&#xff0c;对于G1我有几个疑惑&#xff0c;希望能够在这篇文章中…

微服务~Eureka实现的服务注册与发现及服务之间的调用

微服务里一个重要的概念就是服务注册与发现技术&#xff0c;当你有一个新的服务运行后&#xff0c;我们的服务中心可以感知你&#xff0c;然后把加添加到服务列表里&#xff0c;然后当你死掉后&#xff0c;会从服务中心把你移除&#xff0c;而你作为一个服务&#xff0c;对其它…