文档章节

多维度分析:抽象类和接口的区别

OneAPM蓝海讯通
 OneAPM蓝海讯通
发布于 2015/09/15 11:43
字数 1386
阅读 66
收藏 3

【编者按】本文作者是Sebastian Malaca,是面向对象编程的狂热者,不断深化研究整洁代码和高代码质量。本文中,作者通过多个方面深入剖析抽象类和接口的区别,并结合经验供读者借鉴学习,本文系 OneAPM 工程师编译整理。

在开发人员岗位面试时,是否了解抽象类和接口之间的基本区别是一个很重要的考量因素。

显而易见?

完全不是。笔者面试过很多人,通常问的第一个问题是关于接口和抽象类的区别。但实际上很少有程序员能给出正确的解答。

就这个问题来说,初级程序员可能都会清楚之间的区别,可能也并不一定理解其背后的原因,但其结构上的差异,特别是针对特定语言(几乎和所有的面向对象的语言一样)应该深入了解。

同时,笔者也发现其他职位候选人(有时甚至是高级职位)竟然也不知道这之间的差异,或者只知道的一个或几个。

如果只是需要了解这些内容那并不难,但这些都是面向对象的基础知识,因此想要设计良好的代码必须对其有一个深入的认识。

下面将详细介绍这些基础知识。

继承

下面将从众所周知的接口和抽象类的区别开始。这种差异是关于继承的,任何类都可以实现多个接口,但是只能扩展一个类,也只能有一个父类。

多个类扩展是一个语言特性,它存在于一些面向对象的语言。为什么呢?因为它带来的问题往往多于价值。

当一个类有许多父类时,有一个情况就是完全相同的方法会声明多个,因此必须显式地「告知」究竟需要的是哪一个。

这样的代码通常难以维护,因为对其进行的任何修改或者重构都必须小心地检查。另一方面,如果一个类需要扩展(至少)两个拥有相同方法的类,那么 DRY 规则显然会被破坏(因此需要从别处下手),或者说会干扰到 Single Responsibility Principle (SAP)。

「如果多个类的继承如此糟糕,为什么它可以实现许多接口呢?」——如果这样的问题在你的脑海盘旋,我不得不承认这是一个绝妙的问题。

然而,很简单。每一个接口都是基于函数而不是一个类去实现。所以,即使实现十个不同的接口,每个包含相同的方法声明,内部也不会发生冲突。接口保证了方法的存在,而不是去说明方法的实现,这意味着,只要不违反 SRP ,你完全可以实现多个接口。

方法的可见度

接口中的所有方法都是 Public 的,但对于抽象类的声明并没有这样的规则,当然不能是 Private 。为什么不能 Private?因为一个抽象方法需要在子类中实现,但 Private 无法访问子类,因此不抽象类不可能存在 Private 属性。

接着回归主题。正如上文写道的,接口是一个函数的保证,你可以把它当作使用接口的类和实现这个接口的类之间的一个合约——保证一个特定类将实现所有声明的方法。这也是为什么这些方法必须是 Public 的原因。因为被严格的限制到了实现上,所以其他一切都不成问题。

然而,当涉及到抽象类时并非这样。我们总是可以有不同的类组,除了这几方面基本上不同以外,其他地方几乎一样,类体的公共方法也是非常相似的。在这种情况下,可以创建 Protected 方法来保持类之间的差异。Template Method 就是一个很典型的例子。

声明和定义

接口只能包含方法声明,而抽象类还可以包含方法的定义。

接口的重点在于提供特定函数,而抽象类还在于子类实现的相似性,不仅仅是其中的函数。

常量

接口和抽象类中都可以定义常量。这是因为这些值不依赖于特定对象,对它们来说都是相同的。

属性

抽象类可以包含属性,但接口却不能。原因与声明和定义是一样的。

总结

除了说明差异,笔者也试图解释它产生的原因。这不仅是因为人们发明某个语言时的突发奇想,而是源于语言背后所支撑的理念。

原文链接:Differences Between Abstract Class and Interface

OneAPM 是应用性能管理领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和 SQL 语句的实时抓取。想阅读更多技术文章,请访问 OneAPM 官方博客

本文转载自:http://news.oneapm.com/abstract-interface/

OneAPM蓝海讯通
粉丝 94
博文 631
码字总数 1266889
作品 0
海淀
私信 提问
设计模式-桥接模式

场景分析 商城系统中常见的商品分类,以电脑为例,如何良好的处理商品分类销售的问题? 这个场景有两个维度:电脑类型、电脑品牌。 模式定义: 将抽奖部分与它的实现部分分离,使它们都可以独...

wjk_snail
2016/03/17
16
0
设计模式(六)桥连模式Bridge(结构型)

设计模式(六)桥连模式Bridge(结构型) 1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该...

tantexian
2016/04/10
48
0
Web 故障排除与性能优化工具 - web_log_analyse

webloganalyse 是一个旨在基于 Web 日志进行故障排除和性能优化的工具,这不是一般所说的日志分析/统计解决方案,它不侧重于通常的 PV、UV 等展示,而是在指定时间段内提供细粒度(最小分钟级...

jkklee
03/07
667
1
桥接模式

1 定义 将抽象部分与它的实现部分分离,使之任意删减,而无需受其它约束 2 结构 桥接模式 Abstraction: 定义抽象类的接口,维护一个指向Implementor类型对象的指针,将Client的请求转发给它的I...

芥末无疆sss
2017/11/22
0
0
【设计模式】桥接模式 Bridge Pattern

开篇还是引用吕振宇老师的那篇经典的文章《设计模式随笔-蜡笔与毛笔的故事》。这个真是太经典了,没有比这个例子能更好的阐明桥接模式了,这里我就直接盗来用了。 现在市面上卖的蜡笔很多,...

风之源
2018/08/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
5
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部