专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »博文摘选 » 抽象类和接口:详细解析Java中抽象类和接口的区别 »正文

抽象类和接口:详细解析Java中抽象类和接口的区别

来源: 发布时间:星期一, 2009年11月30日 浏览:0次 评论:0

  java语言中 abstract erface 是支持抽象类定义两种机制正是由于这两种机制存在才赋予了Java强大 面向对象能力abstract erface的间在对于抽象类定义支持方面具有很大相似性甚至可以相互替换因此很多开发者在进 行抽象类定义时对于abstract erface选择显得比较随意其实两者的间还是有很大区别对于它们选择甚至反映出对 于问题领域本质理解、对于设计意图理解是否正确、合理本文将对它们的间区别进行番剖析试图给开发者提供个在 2者的间进行选择依据

  理解抽象类

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

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

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

  从语法定义层面看abstract erface

  在语法层面Java语言对于abstract erface给出了区别定义方式下面以定义个名为Demo抽象类为例来介绍说明这种区别

  使用abstract 方式定义Demo抽象类方式如下:
abstract Demo{
abstract void method1;
abstract void method2;




  使用erface方式定义Demo抽象类方式如下:
erface Demo{
void method1;
void method2;

}



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

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

  首先abstract 在 Java 语言中表示种继承关系个类只能使用次继承关系(Java不支持多继承 -- 转注)但是个类却可以实现多个erface也许这是Java语言设计者在考虑Java对于多重继承支持方面种折中考虑吧

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

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

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

  从设计理念层面看 abstract erface

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

  前面已经提到过abstract 在Java语言中体现了种继承关系要想使得 继承关系合理父类和派生类的间必须存在"is-a"关系即父类和派生类在概念本质上应该是相同对于erface来说则不然并不要求erface实现者和erface定义在概念本质上是 仅仅是实现了erface定义契约而已为了使论述便于理解下面将通过个简单例子进行介绍说明

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

  使用abstract 方式定义Door:
abstract Door{
abstract void open;
abstract void close
}



  使用erface方式定义Door:
erface Door{
void open;
void close;
}



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

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

  解决方案:

  简单在Door定义中增加个alarm思路方法如下:
abstract Door{
abstract void open;
abstract void close
abstract void alarm;
}



  或者
erface Door{
void open;
void close;
void alarm;
}



  那么具有报警功能AlarmDoor定义方式如下:
AlarmDoor extends Door{
void open{…}
void close{…}
void alarm{…}
}



  或者
AlarmDoor implements Door{
void open{…}
void close{…}
void alarm{…}



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

  解决方案 2:

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

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

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

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



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

  小结

  1.abstract 在 Java 语言中表示种继承关系个类只能使用次继承关系但是个类却可以实现多个erface

  2.在abstract 中可以有自己数据成员也可以有非abstarct成员思路方法而在erface中只能够有静态不能被修改数据成员(也就是必须是 final不过在 erface中般不定义数据成员)所有成员思路方法都是abstract

  3.abstract erface所反映出设计理念区别其实abstract 表示是"is-a"关系erface表示是"like-a"关系

  4.实现抽象类和接口类必须实现其中所有思路方法抽象类中可以有非抽象思路方法接口中则不能有实现思路方法

  5.接口中定义变量默认是public final 型且必须给其初值所以实现类中不能重新定义也不能改变其值

  6.抽象类中变量默认是 friendly 型其值可以在子类中重新定义也可以重新赋值

  7.接口中思路方法默认都是 public,abstract 类型

  结论

  abstract erface 是 Java语言中两种定义抽象类方式它们的间有很大相似性但是对于它们选择却又往往反映出对于问题领域中概 念本质理解、对于设计意图反映是否正确、合理它们表现了概念间区别关系(虽然都能够实现需求功能)这其实也是语言惯使用方法希望读者朋友能够细细体会

0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: