java抽象机制_java抽象机制.docx

41528d3028836879cd698677c3999917.gifjava抽象机制.docx

1. 抽象类和接口的区别 所谓抽象类是用来表征我们在对问题领域进行分析、设计中得出的抽象概 念,是对一系列看上去不同,但是本质上相同的具体概念的抽象;所谓接口, 相当于电源插座,可插入构件相当于电器。可插入构件的关键在于存在一个公 用的接口,以及每个构件都实现了这个接口。接口是实现构件的可插入性的关 键。 1.1. 从语法层区别抽象类和接口 从语法层来讲,Java 语言对于抽象类和接口给出了不同的定义方式,下面 以定义一个名为 Demo 的抽象类为例来说明这种不同。 Demo 抽象类的定义方式如下: abstract class Demo { abstract void 1(); abstract void 2(); … } Demo 的接口定义方式如下: interface Demo { void 1(); void 2(); … } 在抽象类的定义中,Demo 可以有自己的数据成员,也可以有非 abstract 的成员方法,而在接口的定义中,Demo 只能够有 static final 数据成员,所有 的成员方法都是 abstract 的。从某种意义上说,接口是一种特殊形式的抽象类。 从编程的角度来看,首先,抽象类和接口的继承规则不同,抽象只允许单 继承,而一个类却可以实现多个接口。接口对于多重继承的支持方面的一种折中考虑;其次,在抽象类的定义中,可以赋予方法的默认行为,而在接口的定 义中,方法不能拥有默认行为,必须使用委托,从某种意义上来说,接口比抽 象类更为抽象化。 1.2. 从设计层上理解抽象类和接口 上面主要从语法层的角度论述了抽象类和接口的区别,这些层面的区别是 比较低层次的、非本质的。本小节将从这个设计层进行分析理解二者概念的本 质。 抽象类在 Java 语言中体现了一种继承关系,要想使得继承关系合理,父 类和派生类之间必须存在“Is-A“关系,即父类和子类在概念本质上应该是相同的。 对于接口来说则不然,接口并不要求实现者和接口定义在概念本质上是一致的, 仅仅是实现了接口定义的契约而已。考虑这样一个例子,假设在有一个关于 Door 的抽象概念,该 Door 具有执行两个动作 open 和 close,此时我们可以通 过抽象类或者接口来定义一个表示该抽象概念的类型,定义方式分别如下所示: Door 抽象类的定义方式如下: abstract class Door { abstract void open(); abstract void close(); } Door 的接口定义方式如下: interface Door { void open(); void close(); } 其他具体的 Door 类型可以 extends 使用抽象类方式定义的 Door 或者 implements 使用接口方式定义的 Door。看起来好像使用抽象类和接口没有大 的区别。如果现在要求 Door 还要具有报警的功能。下面将罗列出可能的解决 方案,并从设计层对方案进行分析。解决方案一: 简单的在 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(){…}} 这种方法违反了接口隔离原则,在 Door 的定义中把 Door 概念本身固有的 行为方法和另外一个概念“报警器”的行为方法混在了一起。这样引起的一个问 题是那些仅仅依赖于 Door 这个概念的模块会因为“报警器”这个概念的改变(比 如:修改 alarm 方法的参数)而改变,反之依然。 解决方案二: 既然 open、close 和 alarm 属于两个不同的概念,根据接口隔离原则应该 把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使 用抽象类方式定义;两个概念都使用接口方式定义;一个概念使用抽象类方式 定义,另一个概念使用接口方式定义。 显然,由于 Java 语言不支持多重继承,所以两个概念都使用抽象类方式 定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对 于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。 如果两个概念都使用接口方式来定义,那么就反映出两个问题:第一,我 们可能没有理解清楚问题领域,AlarmDoor 在概念本质上 到底是 Door 还是报 警器?第二,如果我们对于问题领域的理解没有问题,比如:我们通过对于问 题领域的分析发现 AlarmDoor 在概念本质上和 Door 是一致的,那么我们在实 现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均 使用接口方式定义)反映不出上述含义。 如果我们对于问题领域的理解是:AlarmDoor 在概念本质上是 Door ,同时 它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢? 前面已经说过,抽象类在 Java 语言中表示一种继承关系,而继承关系在本质 上是“Is-A“关系。所以对于 Door 这个概念,我们应该使用抽象类方式来定义。 另外,AlarmDoor 又具有报警功能,说明它又能够完成报警概念中定义的行为, 所以报警概念可以通过接口方式定义。如下所示: 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(){…} } 这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的 揭示我们的设计意图。其实抽象类表示的是“Is-A“ 关系,interface 表示的是 “Has-A“关系,在选择时可以作为一个依据,当然这是建立在对问题领域的理解 上的,比如:如果我们认为 AlarmDoor 在概念本质上是报警器,同时又具有 Door 的功能,那么上述的定义方式就要反过来了。 2. 抽象机制的重要性 抽象机制是面向对象的可复用设计的必要条件。 面向对象的可复用设计的基石是开闭原则,也即一个软件实体应该对扩展 开放,对修改关闭。满足开闭原则的关键就在于抽象化。在 Java 这样的面向 对象的编程语言里,可以给系统

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值