《Effective C#》Item 19:推荐在继承中使用接口

C#抽象类(abstract class)与接口(interface)深度解析 本文详细探讨了C#中抽象类与接口的核心概念、主要区别、设计理念、应用场景以及高级特性。抽象类用于定义“是什么”关系,支持共享代码、状态维护和访问控制,适合作为基类使用。接口则定义“能做什么”关系,支持多重继承和松耦合设计,适合定义组件间契约。文章还对比了两者在结构、功能、版本演进等方面的差异,并提供了具体的使用场景和代码示例。此外,介绍了显式接口实现、默认接口实现等高级特性,以及抽象类与接口的组合使用方式。最后,简要分析了抽象类与接口在运行时性能上的差异。 阅读详情

.Net提供了接口,这个不同于Class或者Struct的类型定义。接口有些情况,看似和抽象类一样,因此有些人认为在.Net可以完全用接口来替换抽象类。其实不然,接口和抽象类各有长处和缺陷,因此往往在应用当中,两者要结合来使用,从而互补长短。

 

接下来先说说抽象类和接口的区别。

区别一,两者表达的概念不一样。抽象类是一类事物的高度聚合,那么对于继承抽象类的子类来说,对于抽象类来说,属于“是”的关系;而接口是定义行为规范,因此对于实现接口的子类来说,相对于接口来说,是“行为需要按照接口来完成”。这些听起来有些虚,举个例子。例如,狗是对于所有狗类动物的统称,京哈是狗,牧羊犬是狗,那么狗的一般特性,都会在京哈,牧羊犬中找到,那么狗相对于京哈和牧羊犬来说,就属于这类事物的抽象类型;而对于“叫”这个动作来说,狗可以叫,鸟也可以叫。很明显,前者相当于所说的是抽象类,而后者指的就是接口。

 

区别二,抽象类在定义类型方法的时候,可以给出方法的实现部分,也可以不给出;而对于接口来说,其中所定义的方法都不能给出实现部分。

例如:

    public abstract class AbsTest

    {

        public virtual void Test()

        {

            Debug.WriteLine( "Test" );

        }

        public abstract void NewTest();

    }

 

    public interface ITest

    {

        void Test();

        void NewTest();

    }

 

区别三,继承类对于两者所涉及方法的实现是不同的。继承类对于抽象类所定义的抽象方法,可以不用重写,也就是说,可以延用抽象类的方法;而对于接口类所定义的方法或者属性来说,在继承类中必须要给出相应的方法和属性实现。

 

区别四,在抽象类中,新增一个方法的话,继承类中可以不用作任何处理;而对于接口来说,则需要修改继承类,提供新定义的方法。

 

知道了两者的区别,再来说说,接口相对于抽象类的优势。

好处一,接口不光可以作用于引用类型,也可以作用于值类型。而抽象类来说,只能作用于引用类型。

 

好处二,.Net的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。其实,我对于这一点也比较赞同,多继承会使继承树变的混乱。

 

好处三,由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。

 

好处四,通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。

 

好处五,减少值类型的拆箱操作。对于Struct定义的值类型数据,当存放集合当中,每当取出来,都需要进行拆箱操作,这时采用Struct+Interface结合的方法,从而降低拆箱操作。

参看如下文章提供的方法。

http://blog.youkuaiyun.com/Knight94/archive/2006/10/08/1326326.aspx

 

相对于抽象类来说,接口有这么多好处,但是接口有一个致命的弱点,就是接口所定义的方法和属性只能相对于继承它的类型(除非在继承类中修改借口定义的函数标示),那么对于多层继承关系的时候,光用接口就很难实现。因为如果让每个类型都去继承接口而进行实现的话,首先不说编写代码比较繁琐,有时候执行的结果还是错误,尤其当子类型对象隐式转换成基类对象进行访问的时候。

那么这时候,需要用接口结合虚方法来实现。参看IDisposable在继承类型中的实现方法。

http://blog.youkuaiyun.com/Knight94/archive/2006/10/10/1329214.aspx

 

其实在继承中,到底使用接口还是抽象类。接口是固定的,约定俗成的,因此在继承类中必须提供接口相应的方法和属性的实现。而对于抽象类来说,抽象类的定义方法的实现,贯穿整个继承树,因此其中方法的实现或者重写都是不确定的。因此相对而言,抽象类比接口更灵活一些。

 

如下给出两者的简单对比表格。

 

接口

抽象类

多继承

支持

不支持

类型限制

没有

有,只能是引用类型

方法实现

继承类型中必须给出方法实现

继承类中可以不给出

扩展性

比较麻烦

相对比较灵活

多层继承

比较麻烦,需要借助虚函数

比较灵活

 

总的来说,接口和抽象类是.Net为了更好的实现类型之间继承关系而提供的语言手段,而且两者有些相辅相成的关系。因此我并不强调用什么而不用什么,那么问题的关键在于,如何把这两种手段合理的应用到程序当中,这才是至关重要。

 
Effective C++与现代C++实践:从RAII到智能指针的编程哲学 在C++编程中,资源管理和内存安全是构建健壮系统的核心基础。RAII(Resource Acquisition Is Initialization)作为一种关键编程范式,通过将资源生命周期与对象绑定,从根本上解决了资源泄露问题。这一原理在现代C++中通过智能指针(如std::unique_ptr、std::shared_ptr)得到了优雅实现,它们不仅自动管理动态内存,还通过所有权语义确保了异常安全。这些技术对于开发高性能服务器、游戏引擎等对稳定性要求极高的应用场景至关重要。本文以《Effective C+ 阅读详情

相关推荐

C#核心特性与开发实践全解析

面向对象编程是现代软件开发的基础范式,C#作为.NET平台的主力语言,通过统一的类型系统和自动内存管理机制实现了高效开发。其核心特性包括泛型编程确保类型安全、LINQ实现声明式数据操作、async/await简化异步编程,这些技术显著提升了工程实践中的开发效率和代码质量。特别是在企业级应用开发中,C#的反射机制和特性系统为元编程提供了强大支持,而委托与事件模型则完善了观察者模式的实现。随着.NET生态的跨平台发展,C#结合Visual Studio等工具链,已成为Web服务、桌面应用和游戏开发等场景的热门选

weixin_30254435的博客 408

c#接口和抽象类的区别

c#接口和抽象类的区别 大家都容易把这两者搞混,我也一样,在听李建忠老师的设计模式时,他也老把抽象类说成接口,弄的我就更糊涂了,所以找了些网上的资料. 一、抽象类: 抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。 二...

huang714的专栏 4471

Azure Blob Storage企业级数据管理:上传、安全与自动化策略

对象存储是现代数据平台的基础设施核心,其本质是为海量非结构化数据提供高可靠、低成本、强一致性的持久化能力。Azure Blob Storage 作为典型代表,通过 RESTful 接口、分层存储(Hot/Cool/Archive)、生命周期策略等机制,实现数据从写入到归档的全周期治理。技术价值在于将权限控制(RBAC + SAS)、加密(SSE/CMK)、网络隔离(VNet/Firewall)深度集成于服务原生能力中,显著降低合规风险与运维复杂度。典型应用场景包括医疗影像归档、IoT日志沉淀、备份数据湖构建

dengwan3818的博客 382

浅谈C#中的抽象类(abstract)和接口(interface)

很多C#的初学者在编程时都容易把抽象类和接口搞混,甚至很多编程老鸟也没有弄明白为什么有了抽象类又搞个接口(这里也包括了本老鸟)。所以这里整理了C#抽象类和接口的区别,详细的分析了抽象类与接口的概念与特性,并对二者作出比对说明。

MarcoPro的博客 4727

C++ 知识补充

向量(vector)是一个封装了动态大小数组的顺序容器(SequenceContainer)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。C++中map提供的是一种键值对容器,里面的数据都是成对出现的,如下图:每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。

weixin_47059239的博客 2130

【继承抽象类和接口的区别】

【继承抽象类和接口的区别】

学无止境 642

Effective C# Item29:只有当新版基类导致问题时才考虑使用new修饰符

我们一般在类成员上使用new修饰符,来重新定义继承自基类的非虚成员,但是我们不建议这么做,因为重新定义非虚方法会导致含混不清的行为。 非虚方法是静态绑定的,编译器并不会根据对象的运行时类型来判断应该调用哪个方法;而虚函数使用的是动态绑定,编译器会根据对象的运行时类型来判断应该调用哪个方法。 避免使用new 修饰符来重新定义非虚方法,并不是说你应该将基类中的所有方法都设计...

weixin_30916125的博客 56

C# 中抽象类与接口的异同

抽象类和接口在 C# 编程中各有其独特的价值。开发者应根据具体的需求来选择使用抽象类还是接口,或者结合两者使用,以构建出更加灵活、可维护的软件系统。如果需要定义一组具有部分实现的通用行为且强调代码复用和层次结构,可选择抽象类;如果需要定义一组行为规范且强调行为的一致性和多态性,接口则是更好的选择。在 C# 编程中,抽象类和接口都是实现代码复用和多态性的重要工具,但它们在很多方面存在差异。理解这些异同,有助于开发者在实际项目中做出恰当的选择,以构建高效且可维护的软件系统。

candy的博客 1533

2024年C++程序员成长路线图:从新手到架构师的完整路径

C++作为一种高性能系统编程语言,其核心价值在于对计算机底层原理的深度控制和高性能计算能力。其设计哲学融合了面向对象、泛型和过程式编程范式,通过RAII(资源获取即初始化)等机制实现安全高效的资源管理。在现代软件开发中,C++的技术价值体现在操作系统、游戏引擎、高频交易、数据库等对性能和可靠性要求极高的领域。随着AI基础设施和边缘计算的发展,掌握C++底层原理和大型系统架构能力成为工程师的核心竞争力。本文基于C++11/14/17/20的现代特性,结合多线程编程、智能指针、STL容器等热词,系统梳理了从语言

weixin_33709609的博客 521

Hermes深入理解及源码解析(二):Hermes的记忆机制

源码位置:tools/memory_tool.py存储内容为两个文件,放在 ~/.hermes/memories/:MEMORY.md:Agent 自己的笔记(环境事实、项目约定、工具坑、学到的东西)—— 上限 2200 字符USER.md:关于用户的画像(角色、偏好、沟通风格)—— 上限 1375 字符作为一个独立的工具注册在系统中(为了让智能体正确使用它,System Prompt()中明确下达了禁令存储目标存储位置数据类型持久偏好/事实MEMORY.md我是谁、我喜欢什么、环境配置。

qq_41984117的博客 559

光伏储能交直流微电网Matlab/Simulink仿真模型

首先是光伏储能交直流微电网,这个也是我还是之前在硕士期间在做光伏扶贫项目时候搭建的仿真,仿真由光伏、蓄电池及负载组成的独立直流微电网,提出电压和电流分段式协同控制策略。接下来我将主要更新关于光伏、风电、储能微电网系统相关的内容,包括具体建模和控制。

2401_89292556的博客 785

C++编程语言深度解析:从核心设计到现代应用实战指南

编程语言作为计算机系统的核心沟通工具,其设计哲学直接影响软件的性能、安全性与可维护性。在众多编程范式中,面向对象编程通过封装、继承和多态等机制,构建出模块化、可复用的代码结构,而泛型编程则借助模板技术实现类型无关的通用算法,这两者共同构成了现代软件工程的基石。C++作为一门支持多范式的中级语言,其独特价值在于实现了“零开销抽象”原则,使得高级编程特性几乎不带来额外运行时损耗,从而在系统软件、游戏引擎、高频交易等对性能有极致要求的领域不可替代。通过智能指针等现代特性,C++在保持底层控制力的同时大幅提升了内存

weixin_34342207的博客 417

使用CLion在Window端进行linux开发

        以往不管是开发x86端linux程序还是arm端linux程序,都是使用Source Insight作为源码编辑工具的,如下图      去年底,发现CLion的2018.3更新版本,可以支持remote host开发了,大爱!     我是基于以下几点原因,将开发工具换成CLion 1. 语法高亮较明显、跳转、重构方便(我很看重这个); 2. 可以使用图形界面进行调...

alist的笔记专栏 1万+

让AI Agent准确生成代码文档:意图对齐与提示词实战指南

AI Agent正从对话问答走向自动化执行,尤其在代码生成、测试与文档维护领域展现出巨大潜力。但要让Agent真正理解你的需求,而非自由发挥,核心在于意图对齐。通过精确的提示词设计、结构化上下文供给与工具调用,Agent能力边界可以被显著扩展。本文从代码文档生成这一典型高频场景切入,讲解如何利用AST解析、上下文工程与一致性校验,构建一个可落地的文档Agent。结合OpenAI兼容接口与Python工具链,展示从模糊指令到精确任务拆解的方法论,并探讨多轮探索式Agent的工程实践。无论你关注智能体开发、自动

weixin_30861797的博客 352

数字通信:信源编码、信道编码、调制、物理信道、解调、信道解码、信源解码

在通信系统中,信息的传输通常需要经过一系列的处理步骤,确保数据可以在信道中高效且可靠地传输。以下是信源编码、信道编码、调制、物理信道、解调、信道解码、信源解码的具体含义及其常见技术的解释。

weixin_44012667的博客 4806

UG NX二次开发(C#)-外部模式-批量删除某些图层中的体对象和曲线对象

在 UG NX中,有时需要批量删除某文件夹下多个.prt文件中固定一些图层中的体对象和曲线对象,这时如果采用手动逐个打开模型,并选择针对的图层删除,即耗时也容易遗漏,因此采用外部模式来处理比较方便。本文介绍批量删除某些图层中的体对象和曲线对象。

GimiGimmy 3035

C++AI编译错误自动修复神器-告别手动Debug的终极方案

在日常 C++ 开发中,编译错误是最频繁遇到的障碍之一。一个中等规模的项目在重构期间,一次 可能产生数十甚至上百条错误信息。这些错误往往具有级联效应——一个头文件的拼写错误可能导致下游十几个翻译单元同时报错,而真正需要修改的地方只有一处。传统的工作流是: 这个循环对于经验丰富的开发者来说尚可接受,但对于以下场景则效率极低:优势:局限:本项目最适合以下场景:阅读

weixin_48053866的博客 280

YOLOv13改进策略【YOLO和Mamba】| 替换骨干 Mamba-YOLOv13-T !!! 最新的发文热点

模块是模型中的一个重要组成部分,其主要作用是在模型的初始阶段对输入图像进行处理,方便后续的特征提取和目标检测。以下是对。

Limiiiing的博客 353

C# 抽象类与接口的区别

一、定义   抽象类:不与具体事物相联系,表达一种抽象的概念,仅是作为其派生类的一个基类。主要用来提供多个派生类可共享的基类的公共定义。   接口:是一种用来定义程序的协议,它描述可属于任何类或结构的一组相关行为,可以看成是实现一组类的模板。 二、相似之处   1.都是引用类型   2.不能直接实例化   3.包含未实现的方法声明   4.派生类必须实现未...

weixin_30902675的博客 1368

JAVA:Spring Boot 集成 LibreOffice 实现文档在线转换服务

本文介绍了在企业级应用开发中使用LibreOffice实现文档格式转换的技术方案。通过对比分析商业库、纯Java方案和云服务API的优缺点,重点阐述了LibreOffice在格式兼容性、转换质量和零成本方面的优势。文章详细说明了环境准备步骤,包括Windows/Linux系统安装LibreOffice、解决中文乱码问题以及Docker部署方案。最后提供了Spring Boot项目的基本配置,包括Maven依赖和application.yml配置文件,为构建稳定高效的文档转换服务奠定基础。

木头 519

Java Swing教程-16. Swing中的图形绘制

这篇教程介绍了Java Swing中的图形绘制功能,主要内容包括: Graphics类的基本使用 - 介绍了如何重写paintComponent方法实现自定义绘制,以及基本图形绘制方法(线条、矩形、椭圆、多边形等) 文本与图片绘制 - 讲解了文本绘制方法、字体设置和图片加载绘制技术 颜色与字体设置 - 包括预定义颜色、RGB自定义颜色、透明色设置以及字体样式控制 案例实现 - 提供了一个简单绘图程序的框架,支持鼠标绘制不同图形、选择工具和自定义颜色等功能 教程通过代码示例详细演示了各种绘图操作,适合Java

无 233

C# 接口和抽象类的区别

一、抽象类 抽象类是仅供派生的类,无法实例化抽象类,只能实例化它派生的类。 定义抽象类和抽象成员时,要为其添加abstract修饰符。 不可实例化只是抽象类的一个次要的特征,其主要特征是它包含抽象成员。 抽象成员不能声明为私有,否则,派生类无法找到它们。 二、接口 1.和抽象类不同,接口不包含任何实现,而且,接口能把提供的服务和实现细节完全隔离开。 2.关键特点:既不包含实现,也不包含数据。...

mozhi 1976

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

上一篇: 借助WebService实现多线程上传文件
下一篇: 怎么用C#制作印章
Knight94
博客等级 码龄25年 1013粉丝 87原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值