首页
|
新闻
|
新品
|
文库
|
方案
|
视频
|
下载
|
商城
|
开发板
|
数据中心
|
座谈新版
|
培训
|
工具
|
博客
|
论坛
|
百科
|
GEC
|
活动
|
主题月
|
电子展
注册
登录
论坛
博客
搜索
帮助
导航
默认风格
uchome
discuz6
GreenM
»
MCU 单片机技术
»
ARM
» Java 抽象类与接口(3)抽象类与接口的区别
返回列表
回复
发帖
发新话题
发布投票
发布悬赏
发布辩论
发布活动
发布视频
发布商品
Java 抽象类与接口(3)抽象类与接口的区别
发短消息
加为好友
look_w
当前离线
UID
1066743
帖子
8283
精华
0
积分
4142
阅读权限
90
在线时间
233 小时
注册时间
2017-6-23
最后登录
2019-5-18
论坛元老
UID
1066743
1
#
打印
字体大小:
t
T
look_w
发表于 2018-12-15 14:15
|
只看该作者
Java 抽象类与接口(3)抽象类与接口的区别
三、抽象类与接口的区别尽管抽象类和接口之间存在较大的相同点,甚至有时候还可以互换,但这样并不能弥补他们之间的差异之处。下面将从语法层次和设计层次两个方面对抽象类和接口进行阐述。
3.1语法层次在语法层次,java 语言对于抽象类和接口分别给出了不同的定义。下面已 Demo 类来说明他们之间的不同之处。
[url=]
[/url]
使用抽象类来实现:
public
abstract
class
Demo {
abstract
void
method1();
void
method2(){
//
实现
} }使用接口来实现
interface
Demo {
void
method1();
void
method2(); }
[url=]
[/url]
抽象类方式中,抽象类可以拥有任意范围的成员数据,同时也可以拥有自己的非抽象方法,但是接口方式中,它仅能够有静态、不能修改的成员数据(但是我们一般是不会在接口中使用成员数据),同时它所有的方法都必须是抽象的。在某种程度上来说,接口是抽象类的特殊化。
对子类而言,它只能继承一个抽象类(这是 java 为了数据安全而考虑的),但是却可以实现多个接口。
3.2设计层次上面只是从语法层次和编程角度来区分它们之间的关系,这些都是低层次的,要真正使用好抽象类和接口,我们就必须要从较高层次来区分了。只有从设计理念的角度才能看出它们的本质所在。一般来说他们存在如下三个不同点:
1、 抽象层次不同。抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
2、 跨域不同。抽象类所跨域的是具有相似特点的类,而接口却可以跨域不同的类。我们知道抽象类是从子类中发现公共部分,然后泛化成抽象类,子类继承该父类即可,但是接口不同。实现它的子类可以不存在任何关系,共同之处。例如猫、狗可以抽象成一个动物类抽象类,具备叫的方法。鸟、飞机可以实现飞 Fly 接口,具备飞的行为,这里我们总不能将鸟、飞机共用一个父类吧!所以说抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is-a"关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的, 仅仅是实现了接口定义的契约而已。
3、 设计层次不同。对于抽象类而言,它是自下而上来设计的,我们要先知道子类才能抽象出父类,而接口则不同,它根本就不需要知道子类的存在,只需要定义一个规则即可,至于什么子类、什么时候怎么实现它一概不知。比如我们只有一个猫类在这里,如果你这是就抽象成一个动物类,是不是设计有点儿过度?我们起码要有两个动物类,猫、狗在这里,我们在抽象他们的共同点形成动物抽象类吧!所以说抽象类往往都是通过重构而来的!但是接口就不同,比如说飞,我们根本就不知道会有什么东西来实现这个飞接口,怎么实现也不得而知,我们要做的就是事前定义好飞的行为接口。所以说抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。
(上面纯属个人见解,如有出入、错误之处,望各位指点!!!!)
为了更好的阐述他们之间的区别,下面将使用一个例子来说明。该例子引自:
我们有一个 Door 的抽象概念,它具备两个行为 open() 和 close(),此时我们可以定义通过抽象类和接口来定义这个抽象概念:
抽象类:
[url=]
[/url]
abstract
class
Door{
abstract
void
open();
abstract
void
close(); }接口
interface
Door{
void
open();
void
close(); }
[url=]
[/url]
至于其他的具体类可以通过使用 extends 使用抽象类方式定义 Door 或者 Implements 使用接口方式定义 Door,这里发现两者并没有什么很大的差异。
但是现在如果我们需要门具有报警的功能,那么该如何实现呢?
解决方案一:给 Door 增加一个报警方法:clarm();
[url=]
[/url]
abstract
class
Door{
abstract
void
open();
abstract
void
close();
abstract
void
alarm(); }或者
interface
Door{
void
open();
void
close();
void
alarm(); }
[url=]
[/url]
这种方法违反了面向对象设计中的一个核心原则 ISP (Interface Segregation Principle)—见批注,在 Door 的定义中把 Door 概念本身固有的行为方法和另外一个概念"报警器"的行为方 法混在了一起。这样引起的一个问题是那些仅仅依赖于 Door 这个概念的模块会因为”报警器”这个概念的改变而改变,反之依然。
解决方案二
既然 open()、close() 和alarm() 属于两个不同的概念,那么我们依据 ISP 原则将它们分开定义在两个代表两个不同概念的抽象类里面,定义的方式有三种:
1、两个都使用抽象类来定义。
2、两个都使用接口来定义。
3、一个使用抽象类定义,一个是用接口定义。
由于 Java 不支持多继承所以第一种是不可行的。后面两种都是可行的,但是选择何种就反映了你对问题域本质的理解。
如果选择第二种都是接口来定义,那么就反映了两个问题:1、我们可能没有理解清楚问题域,AlarmDoor 在概念本质上到底是门还报警器。2、如果我们对问题域的理解没有问题,比如我们在分析时确定了 AlarmDoor 在本质上概念是一致的,那么我们在设计时就没有正确的反映出我们的设计意图。因为你使用了两个接口来进行定义,他们概念的定义并不能够反映上述含义。
第三种,如果我们对问题域的理解是这样的:AlarmDoor 本质上 Door,但同时它也拥有报警的行为功能,这个时候我们使用第三种方案恰好可以阐述我们的设计意图。AlarmDoor 本质是们,所以对于这个概念我们使用抽象类来定义,同时 AlarmDoor 具备报警功能,说明它能够完成报警概念中定义的行为功能,所以 alarm 可以使用接口来进行定义。如下:
[url=]
[/url]
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(){} }
[url=]
[/url]
这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实抽象类表示的是"is-a"关系,接口表示的是"like-a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为 AlarmDoor 在概念本质上是报警器,同时又具有 Door 的功能,那么上述的定义方式就要反过来了。
批注: ISP(Interface Segregation Principle)`:面向对象的一个核心原则。它表明使用多个专门的接口比使用单一的总接口要好。
一个类对另外一个类的依赖性应当是建立在最小的接口上的。
一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。
收藏
分享
评分
回复
引用
订阅
TOP
返回列表
PCB综合技术
电商论坛
Pine A64
资料下载
方案分享
FAQ
行业应用
消费电子
便携式设备
医疗电子
汽车电子
工业控制
热门技术
智能可穿戴
3D打印
智能家居
综合设计
示波器技术
存储器
电子制造
计算机和外设
软件开发
分立器件
传感器技术
无源元件
资料共享
PCB综合技术
综合技术交流
EDA
MCU 单片机技术
ST MCU
Freescale MCU
NXP MCU
新唐 MCU
MIPS
X86
ARM
PowerPC
DSP技术
嵌入式技术
FPGA/CPLD可编程逻辑
模拟电路
数字电路
富士通半导体FRAM 铁电存储器“免费样片”使用心得
电源与功率管理
LED技术
测试测量
通信技术
3G
无线技术
微波在线
综合交流区
职场驿站
活动专区
在线座谈交流区
紧缺人才培训课程交流区
意见和建议