抽象类和接口的区别

NVIDIA Orin AGX开发环境搭建避坑指南:从Ubuntu 22.04到ROS2完整配置流程 本文详细介绍了NVIDIA Orin AGX开发环境搭建的全流程,从Ubuntu 22.04系统安装到ROS2深度优化,涵盖驱动部署、CUDA环境配置、散热与功耗管理等关键步骤。特别针对Orin AGX的特性提供了实用避坑指南和性能优化技巧,帮助开发者高效完成开发环境配置。 阅读详情
下面的这篇文章讲的十分透彻了,所以转载之
abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。  

理解抽象类  

abstract class和interface在Java语言中都是用来进行抽象类(本文中的抽象类并非从abstract class翻译而来,它表示的是一个抽象体,而abstract class为Java语言中用于定义抽象类的一种方法,请读者注意区分)定义的,那么什么是抽象类,使用抽象类能为我们带来什么好处呢?  

在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。  

在面向对象领域,抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。熟悉OCP的读者一定知道,为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。  


从语法定义层面看abstract class和interface  

在语法层面,Java语言对于abstract class和interface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。  

使用abstract class的方式定义Demo抽象类的方式如下:  

abstract class Demo {  
 abstract void method1();  
 abstract void method2();  
 …  
}  

使用interface的方式定义Demo抽象类的方式如下:  

interface Demo {  
 void method1();  
 void method2();  
 …  
}  

在abstract class方式中,Demo可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface方式的实现中,Demo只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。从某种意义上说,interface是一种特殊形式的abstract class。  

      从编程的角度来看,abstract class和interface都可以用来实现"design by contract"的思想。但是在具体的使用上面还是有一些区别的。  

首先,abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。  

其次,在abstract class的定义中,我们可以赋予方法的默认行为。但是在interface的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会 增加一些复杂性,有时会造成很大的麻烦。  

在抽象类中不能定义默认行为还存在另一个比较严重的问题,那就是可能会造成维护上的麻烦。因为如果后来想修改类的界面(一般通过abstract class或者interface来表示)以适应新的情况(比如,添加新的方法或者给已用的方法中添加新的参数)时,就会非常的麻烦,可能要花费很多的时间(对于派生类很多的情况,尤为如此)。但是如果界面是通过abstract class来实现的,那么可能就只需要修改定义在abstract class中的默认行为就可以了。  

同样,如果不能在抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了"one rule,one place"原则,造成代码重复,同样不利于以后的维护。因此,在abstract class和interface间进行选择时要非常的小心。  


从设计理念层面看abstract class和interface  

上面主要从语法定义和编程的角度论述了abstract class和interface的区别,这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面:abstract class和interface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。  

前面已经提到过,abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的(参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述,有兴趣的读者可以参考)。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。  

考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:  

使用abstract class方式定义Door:  

abstract class Door {  
 abstract void open();  
 abstract void close();  
}  

   
使用interface方式定义Door:  


interface Door {  
 void open();  
 void close();  
}  

   
其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。  

如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中,主要是为了展示abstract class和interface反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。  

解决方案一:  

简单的在Door的定义中增加一个alarm方法,如下:  

abstract class Door {  
 abstract void open();  
 abstract void close();  
 abstract void alarm();  
}  

   
或者  

interface Door {  
 void open();  
 void close();  
 void alarm();  
}  

   
那么具有报警功能的AlarmDoor的定义方式如下:  

class AlarmDoor extends Door {  
 void open() { … }  
 void close() { … }  
 void alarm() { … }  
}  

   
或者  

class AlarmDoor implements Door {  
 void open() { … }  
 void close() { … }  
 void alarm() { … }  
}  

这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。  

解决方案二:  

既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用abstract class方式定义;两个概念都使用interface方式定义;一个概念使用abstract class方式定义,另一个概念使用interface方式定义。  

显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。  

如果两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用interface方式定义)反映不出上述含义。  

如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:  

abstract class Door {  
 abstract void open();  
 abstract void close();  
}  
interface Alarm {  
 void alarm();  
}  
class AlarmDoor extends Door implements Alarm {  
 void open() { … }  
 void close() { … }  
    void alarm() { … }  
}  

   
这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。 
DRM全解析 —— encoder详解(3) 阅读详情

相关推荐

VMFS数据存储(datastore)丢失后恢复步骤

vmfs datastore恢复步骤

jetliu05的博客 3265

接口和抽象类有什么区别

接口和抽象类有什么区别 你选择使用接口和抽象类的依据是什么? 接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。 抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。 人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它. 所以,在高级

冯立彬的博客 27万+

React项目实战:用AntV G6打造可折叠组织架构图(附完整代码)

本文详细介绍了如何在React项目中使用AntV G6库构建一个功能完整的可折叠组织架构图。通过实战代码演示了从环境搭建、自定义节点、折叠状态管理到性能优化的全流程,重点解决了企业级应用中处理复杂树形数据、实现流畅交互等核心问题,并提供了可直接复用的组件代码。

weixin_29016315的博客 312

接口和抽象类的区别

前言: 抽象类和接口都是在一定程度上体现到了java的多态特性。那么在使用场景上,它们有什么区别呢? 在语法方面: 抽象类: 1.由abstract关键词修饰的类称之为抽象类。 2.抽象类中没有实现的方法称之为抽象方法,也需要加关键字abstract。 3.抽象类中也可以没有抽象方法,比如HttpServlet方法。 4.抽象类中可以有已经实现的方法,可以定义成员变量。 接口: 1.由interface关键词修饰的称之为接口; 2.接口中可以定义成员变量,但是这些成员变量默认都是public stat

weixin_49794051的博客 7856

自抗扰控制(ADRC)原理与MATLAB实现详解

自抗扰控制(ADRC)是一种先进的鲁棒控制策略,其核心在于通过扩张状态观测器(ESO)实时估计并补偿系统总扰动。相比传统PID控制,ADRC不依赖精确数学模型,特别适合处理非线性、时变系统。从控制原理看,ADRC将系统内部动态和外部扰动统一建模,通过带宽参数化方法实现快速响应与强抗扰能力。在工程实践中,ADRC已成功应用于无人机飞控、伺服系统等场景,MATLAB仿真显示其上升时间可比PID提升46%,抗扰动恢复时间缩短60%。典型实现包含ESO设计、扰动补偿和PD控制三部分,参数整定遵循ω₀=3~5倍系统带

weixin_33585822的博客 93

知识导航神器:Obsidian Breadcrumbs 插件全攻略

Parent: 插件Child: Breadcrumbs 用法这样,它就能识别出你和其他笔记的关系。

m0_73735578的博客 1628

Java中抽象类和接口的区别

从这里可以看出,抽象类就是为了继承而存在的,如果你定义了一个抽象类,却不去继承它,那么等于白白创建了这个抽象类,因为你不能用它来做任何事情。对于一个父类,如果它的某个方法在父类中实现出来没有任何意义,必须根据子类的实际需求来进行不同的实现,那么就可以将这个方法声明为abstract方法,此时这个类也就成为abstract类了。包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。

2401_84003630的博客 922

【踩坑记录】Latex引文bib报错

VScode+Texlive+Zotero本地论文写作环境踩坑。解决Zotero导出bib文件后tex中通过cite引用时所产生的问题。

weixin_43319948的博客 2823

Java 抽象类和接口的区别

1、定义 1) 抽象类(abstract class) 官方定义:如果一个类没有包含足够多的信息来描述一个具体的对象,这样的类就是抽象类。简单来说就是使用abstract修饰符修饰的类。 实际点来说,一个抽象类不能实例化,因为“没有包含足够多的信息来描述一个具体的对象”。但终归属于类,所以仍然拥有普通类一样的定义。依然可以在类的实体(直白点就是能在{}里面)定义成员变量,成员方法,构造方法等。 那么可能初学者会问:既然不能实例化,那么在类里面定义成员方法,成员变量有什么用。 ...

qq_45849148的博客 3608

RK3399平台开发系列讲解(内核入门篇)1.1、通过sysfs清楚了解设备的系统状况

文章目录1、不敢高声语,恐惊天上人:sysfs目的2、窥一斑而知全豹:sysfs目录介绍3、千丝万缕:sysfs中要素的关系4、数据观星:sysfs中相关结构体 1、不敢高声语,恐惊天上人:sysfs目的 我们想通过sys下面的目录和文件清楚的了解跑Liunx系统的嵌入式设备的系统状况。 2、窥一斑而知全豹:sysfs目录介绍 sysfs把连接在系统上的设备和总线组织成为一个分级的文件,它们可以由用户空间存取,向用户空间导出内核的数据结构以及它们的属性。sysfs的一个目的就是展示设备驱动模型中各组件.

内核笔记 1万+

MySQL数据库面试题(2022版)

序列号 内容 链接 1 Java基础知识面试题(2022版) https://blog.youkuaiyun.com/qq_43061290/article/details/124023797 2 Java集合容器面试题(2022版) https://blog.youkuaiyun.com/qq_43061290/article/details/124043363 3 Java异常面试题(2022版) https://blog.youkuaiyun.com/qq_43061290/article/details/124....

拉格朗日的学习笔记 1万+

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

抽象类和接口的区别、联系 抽象类abstract class 抽象方法和抽象类必须使用abstract修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法。 ​ 抽象方法和抽象类的规则如下。 抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体 抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。即使抽象类里不包含抽象方法,这个抽象类也不能创建实例。 抽象类可以包含成员变量、方法(普通方法和抽象方法都

qq_45690664的博客 164

具身智能 | 从具身智能出发谈多传感器融合技术

多传感器融合感知是具身智能系统突破“感知—认知—行动”闭环的核心使能技术。本文从具身智能的视角出发,对多传感器融合技术进行系统综述。首先阐述了具身智能对多传感器融合提出的独特需求,包括异构感知集成、跨模态语义对齐和实时闭环决策。其次,构建了多层级融合技术分类框架,从数据层融合、特征层融合、决策层融合、时序融合到多模态大语言模型(MLLM)融合,逐层梳理主流方法与演进脉络。在此基础上,分析了面向具身智能的通用融合架构设计,涵盖了感知—推理—执行三层架构及其关键组件。

尘世冰封的专栏 310

抽象类和接口的区别简单总结

搞java几年了突然被领导问了这么一个问题,最终没有说服领导,看了一些资料现在总结一下。 1、语法层面上的区别 1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法; 2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的; 3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和...

zzqcsdn123的专栏 2248

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

抽象类和接口的区别—简述

抽象类 抽象类是特殊的类,使用abstract定义,它可以包含普通类所能定义的任何种属性和方法,只是在抽象类中,包含一种普通类所没有的抽象方法。 eg:比如我们现实生活中有一种方法叫做“说话”,他相当一种抽象类,那么会说话的物种世上千千万,小猫说“喵喵”,小狗说“汪汪”,小青蛙说“呱呱”。所有物种说的内容都不相同,那么在“说话”这个方法中就不能规定一种实例。这是需要每一个子类自己去实现自己的“说话”方法的。 · 抽象类是不可以被实例化的。 · 抽象类和普通类的区别就在于多了一个抽象方法,不能被实例化。

weixin_46448719的博客 3478

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

简述抽象类和接口、抽象类区别的区别

抽象类和普通类和接口什么是抽象类什么是接口抽象类和接口区别 什么是抽象类 用abstract修饰的类叫抽象类 1、抽象类不能有对象,抽象类不能实例化,不能new 2、abstract修饰的方法为抽象方法,这种方法不能有方法体(什么内容都没有) 3、抽象类不能有对象,不能new对象 4、有抽象方法的一定是抽象类,抽象类中不一定有抽象方法 5、抽象类型中的抽象方法必须在子类中被重写 抽象类不能被实例化,抽象方法必须被重写,定义它们是干嘛? 抽象类是用来被继承的,如果没有类去继承它,也就失去了意义;抽象方法生来就

char_m的博客 827

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

接口和抽象类的区别?

抽象类(模板) | | 接口(能力) || |is-a 抽象父类 can-do 能力规范| |可包含状态/构造器/方法逻辑 只能定义常量和行为声明| |单继承限制 多接口实现| |用于通用逻辑抽取/框架模板 用于功能扩展、事件回调、能力声明如你有兴趣,我可以深入讲讲“接口 + default 方法”是如何在函数式接口、策略模式、SPI 插件扩展中发挥关键作用的,是否继续?

weixin_46072507的博客 351

接口和抽象类的区别,实不相瞒,我忘记了?

接口和抽象类的区别,实不相瞒,我忘记了? 在Java基础部分,接口和抽象类是相当重要的知识点,尤其是接口,在后面的开发中,经常会见到这么四个字“面向接口编程”,而且对于接口和抽象类的知识也是面试中经常会被问到的,所以我们非常有必要熟练掌握这部分的知识!今天吗,我们就一起来回顾下! 小白: 庆哥,说真的,现在让我来说接口和抽象类的区别,我发现自己的记忆是模糊的,能说出来的大概就是: 接...

庆哥Java的优快云技术博客 2051
上一篇: 解读IT人从业方向
下一篇: 如何判断一个网页是刷新还是关闭的方法。
soleghost
博客等级 码龄24年 23粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值