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

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

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

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

来源: 发布时间:星期四, 2009年3月19日 浏览:0次 评论:0
在Java语言中 abstract erface 是支持抽象类定义两种机制正是由于这两种机制存在才赋予了Java强大 面向对象能力abstract erface的间在对于抽象类定义支持方面具有很大相似性甚至可以相互替换因此很多开发者在进 行抽象类定义时对于abstract erface选择显得比较随意其实两者的间还是有很大区别对于它们选择甚至反映出对 于问题领域本质理解、对于设计意图理解是否正确、合理本文将对它们的间区别进行番剖析试图给开发者提供个在 2者的间进行选择依据
+U1_2WM:e([,E|b#Bq ]0tJAVA中文站社区门户 `Q*S!E5Y6C&@Ai8R
  理解抽象类JAVA中文站社区门户5At Z'h3?oh

4OQ|Z^YYY:p[  abstract erface在Java语言中都是用来进行抽象类(本文 中抽象类并非从abstract 翻译而来它表示个抽象体而abstract 为Java语言中用于定义抽象类种思路方法 请读者注意区分)定义那么什么是抽象类使用抽象类能为我们带来什么好处呢?
Mbl a+f8dL)SJAVA中文站社区门户V2D*xj X
  在 面向对象概念中我们知道所有对象都是通过类来描绘但是反过来却不是这样并不是 所有类都是用来描绘对象如果个类中没有包含足够信息来描绘个具体对象这样类就是抽象类抽象类往往用来表征我们在对问题领域进行分析、 设计中得出抽象概念是对系列看上去区别但是本质上相同具体概念抽象比如:如果我们进行个图形编辑软件Software开发就会发现问题领域存在着圆、 3角形这样些具体概念它们是区别但是它们又都属于形状这样个概念形状这个概念在问题领域是不存在它就是个抽象概念正是抽象概念 在问题领域没有对应具体概念所以用以表征抽象概念抽象类是不能够例子化JAVA中文站社区门户6Aa*ujK
JAVA中文站社区门户 ~E7In4|;_]myn1~
  在面向对象领域抽象类主要用来进行类型隐藏 我们可以构造出个固定组行为抽象描 述但是这组行为却能够有任意个可能具体实现方式这个抽象描述就是抽象类而这组任意个可能具体实现则表现为所有可能派生类模块可以操作个 抽象体由于模块依赖于个固定抽象体因此它可以是不允许修改;同时通过从这个抽象体派生也可扩展此模块行为功能熟悉OCP读者定知 道为了能够实现面向对象设计个最核心原则OCP(Open-Closed Principle)抽象类是其中关键所在
3aY2TkD0L I!Q9J'pv*QJAVA中文站社区门户;dtlDwD
  从语法定义层面看abstract erfaceJAVA中文站社区门户*u t/Jk-|/DH

}/o;g A5`  在语法层面Java语言对于abstract erface给出了区别定义方式下面以定义个名为Demo抽象类为例来介绍说明这种区别JAVA中文站社区门户.E5{\1?dm

"cK:I(ED.r  使用abstract 方式定义Demo抽象类方式如下:
9xA3@pqZ4B-NFT-eJAVA中文站社区门户 XVN-eni
abstract Demo{JAVA中文站社区门户^9x F1i`Xj/s.x
abstract void method1;JAVA中文站社区门户%K M3k,F h+Ib6e
abstract void method2;
%NePB(j/m nx
4mO,~K;J dB1p`JAVA中文站社区门户jq_fG0lk\
JAVA中文站社区门户;k"WA,R doTa
  使用erface方式定义Demo抽象类方式如下:JAVA中文站社区门户jT H[me,s#x

:S/? uj&yq/tWv^erface Demo{JAVA中文站社区门户g6T;G OD s_
void method1;
'N5w8_F1ot#evoid method2;JAVA中文站社区门户5jVUv#})_

4D(uUOF/}6C} JAVA中文站社区门户d4`| m4I2l$F@1@9B

,b8ki6KJC  在abstract 方式中Demo可以有自己数据成员也可以有非 abstract成员思路方法而在erface方式实现中Demo只能够有静态不能被修改数据成员(也就是必须是 final 不过在erface中般不定义数据成员)所有成员思路方法都是abstract从某种意义上说erface是种特殊形式 abstract
U/~|8k A9UJAVA中文站社区门户\ ]&S\JRW5w
  从编程角度来看abstract erface都可以用来实现 "design by contract" 思想但是在具体使用上面还是有些区别
0^7}r1M#gTJAVA中文站社区门户*p9e0f[0_-N
  首先abstract 在 Java 语言中表示种继承关系个类只能使用次继承关系(Java不支持多继承 -- 转注)但是个类却可以实现多个erface也许这是Java语言设计者在考虑Java对于多重继承支持方面种折中考虑吧
E4h*pGu'g;a6sJAVA中文站社区门户$jt:dGK pm$L
  其次在abstract 定义中我们可以赋予思路方法默认行为但是在erface定义中思路方法却不能拥有默认行为为了绕过这个限制必须使用委托但是这会增加些复杂性有时会造成很大麻烦JAVA中文站社区门户$MZ@T8Rsn [8CI
JAVA中文站社区门户2KYRoh]
  在 抽象类中不能定义默认行为还存在另个比较严重问题那就是可能会造成维护上麻烦因 为如果后来想修改类界面(般通过 abstract 或者erface来表示)以适应新情况(比如添加新思路方法或者给已用思路方法中添 加新参数)时就会非常麻烦可能要花费很多时间(对于派生类很多情况尤为如此)但是如果界面是通过abstract 来实现那 么可能就只需要修改定义在abstract 默认行为就可以了
}{ t"q4{7YQ
Y(W;N#r W(jz  同样如果不能在抽象类中定义默认行为就会导致同样思路方法实现出现在该抽象类个派生类中违反了 "one ruleone place" 原则造成代码重复同样不利于以后维护因此在abstract erface间进行选择时要非常小心
&e-K eX p O
&^0ii7O)I3R  从设计理念层面看 abstract erfaceJAVA中文站社区门户+QJ#L6k!C7Xk
JAVA中文站社区门户-`})]%It2me_
  上面主要从语法定义和编程角度论述了abstract erface区 别这些层面区别是比较低层次、非本质本小节将从另个层面:abstract erface所反映出设计理念来分析下 2者区别作者认为从这个层面进行分析才能理解 2者概念本质所在JAVA中文站社区门户&A J+A_&il*d-w
JAVA中文站社区门户1U$lVaM.}
  前面已经提到过abstract 在Java语言中体现了种继承关系要想使得 继承关系合理父类和派生类的间必须存在"is-a"关系即父类和派生类在概念本质上应该是相同对于erface来说则不然并不要求erface实现者和erface定义在概念本质上是 仅仅是实现了erface定义契约而已为了使论述便于理解下面将通过个简单例子进行介绍说明
.x1i'lW4Z3s9U-_{diJAVA中文站社区门户W:`/F.v7p'BxQ
  考虑这样个例子假设在我们问题领域中有个有关Door抽象概念该Door具有执行两个动作open和close此时我们可以通过abstract 或者erface来定义个表示该抽象概念类型定义方式分别如下所示:
^1aX!q:`a2n9i
`,k1iDikKW G  使用abstract 方式定义Door:JAVA中文站社区门户j8k{5w)fe F9d
JAVA中文站社区门户 hMbvF*H
abstract Door{JAVA中文站社区门户i yr,A3l$ZP/~
abstract void open;JAVA中文站社区门户 qi^+ptD
abstract void closeJAVA中文站社区门户g%gIt?
}
T/w~"N6bJAVA中文站社区门户1EA p`)RN3l:c5m
  使用erface方式定义Door:
3D5Ll2u(D,z$KR
/`@Tg;pSY Ferface Door{
f3|6HP Adj1tvoid open;JAVA中文站社区门户,N1`5ryrx4?fS7g
void close;
L!S2K y.Ze ]!?'~3`']@}
|n N7\ XE#TRJAVA中文站社区门户 U"Z6k e9J} zSZ
  其他具体Door类型可以extends使用abstract 方式定义Door或者implements使用erface方式定义Door看起来好像使用abstract erface没有大区别
Fcc!d4l.iqZ zZJAVA中文站社区门户!J!t0[{.BU
  如果现在要求Door还要具有报警功能我们该如何设计针对该例子类结构呢(在本例中 主要是为了展示 abstract erface 反映在设计理念上区别其他方面无关问题都做了简化或者忽略)?下面将罗列出可能解 决方案并从设计理念层面对这些区别方案进行分析JAVA中文站社区门户.FFPC+F`

(IBmdz~-\.I1B  解决方案:JAVA中文站社区门户8c n r9[9M&~mp0w4\u
JAVA中文站社区门户w%BQ3ez6GR
  简单在Door定义中增加个alarm思路方法如下:
)WL;xXM.P&VJAVA中文站社区门户-JZ$O S&a2E6i
abstract Door{
^z?[&]abstract void open;
@C9R$A v?`eabstract void closeJAVA中文站社区门户+o |A9IB lq'q#D
abstract void alarm;JAVA中文站社区门户$uFhjEw
}
I*c D Q [2\JAVA中文站社区门户;V(kG"a [q:A:}
  或者
&T.v!yjR7g4KH7TZ
fNlU(c Nerface Door{JAVA中文站社区门户`;K;gs(w*_/U
void open;
*Mvc.r4V"Ln?void close;JAVA中文站社区门户?*~"zk#c)Z
void alarm;
z WO9s3U0D1us}
B4`,S*Kf-l+GJAVA中文站社区门户:j1S[?Q I
  那么具有报警功能AlarmDoor定义方式如下:JAVA中文站社区门户&x7]i1rUK u

Z [rSb E5Yp AlarmDoor extends Door{
)XIrLV H kvoid open{…}JAVA中文站社区门户`*DAn1X/hz-c
void close{…}
T:W"RARBvoid alarm{…}JAVA中文站社区门户H,zt ^Cw8|Pc:D
} JAVA中文站社区门户 ~$Ls8p0^ Dp+K9bR#P

C W s#s(kB5Ek  或者JAVA中文站社区门户 G8_5K&i\(t+I&I0N
JAVA中文站社区门户2UH*iBo;]U
AlarmDoor implements Door{JAVA中文站社区门户!iBcOM9j K
void open{…}JAVA中文站社区门户*P)V9NQ ?
void close{…}
"uR2{/L6WSmnZvoid alarm{…}JAVA中文站社区门户B |5E NR]-f
JAVA中文站社区门户*I!ZNgv
JAVA中文站社区门户;gX xfg qyF-_H7@
  这种思路方法违反了面向对象设计中个核心原则 ISP (Interface Segregation Principle)在Door定义中把Door概念本身固有行为思路方法和另外个概念"报警器"行为方 法混在了这样引起个问题是那些仅仅依赖于Door这个概念模块会"报警器"这个概念改变(比如:修改alarm思路方法参数)而改变反 的依然JAVA中文站社区门户 tK K&|#l cv

6o/bw7gdd&JEQ  解决方案 2:JAVA中文站社区门户.~Q(nTG9m6b

5Lh8N0i;O8X,l$N  既然open、close和alarm属于两个区别概念根据ISP原则应该把它们分别定 义在代表这两个概念抽象类中定义方式有:这两个概念都使用 abstract 方式定义;两个概念都使用erface方式定义;个概念 使用 abstract 方式定义个概念使用erface方式定义
5_|n']a:mJAVA中文站社区门户1_9_0V _E q1E
  显然由于Java语言不支持多重继承所以两个概念都使用abstract 方式定义是不可行后面两种方式都是可行但是对于它们选择却反映出对于问题领域中概念本质理解、对于设计意图反映是否正确、合理我们来分析、介绍说明JAVA中文站社区门户(`8F:z1\j#At)CLz `\
JAVA中文站社区门户to5D o+wE p&O
  如果两个概念都使用erface方式来定义那么就反映出两个问题:1、我们可能没有 理解清楚问题领域AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域理解没有问题比如:我们通过对于问题领域分 析发现AlarmDoor在概念本质上和Door是那么我们在实现时就没有能够正确揭示我们设计意图在这两个概念定义上(均使用 erface方式定义)反映不出上述含义JAVA中文站社区门户 CE~3ZPH4WQ

YPs-L}%j  如果我们对于问题领域理解是:AlarmDoor在概念本质上是Door同时它有具有报 警功能我们该如何来设计、实现来明确反映出我们意思呢?前面已经说过abstract 在Java语言中表示种继承关系而继承关系 在本质上是"is-a"关系所以对于Door这个概念我们应该使用abstarct 方式来定义另外AlarmDoor又具有报警功能说 明它又能够完成报警概念中定义行为所以报警概念可以通过erface方式定义如下所示:JAVA中文站社区门户x$f m%BTLq(A#\,vE.G

0{,C`1G%pY9Rabstract Door{
Hqg'l+q@rn&Kabstract void open;JAVA中文站社区门户qN8Wi$VlF0G
abstract void closeJAVA中文站社区门户{@a/L,v5t^
}
-gDh*v*D}erface Alarm{
K{?@+mC(yzvoid alarm;JAVA中文站社区门户K nq L x.Y)?W`sc
}JAVA中文站社区门户M_.{a8p1}3\ |3~
Alarm Door extends Door implements Alarm{
$Lf&Hoe+Y}C4F%h^void open{…}
8c\,N(S~void close{…}
,h/r ?$Glvoid alarm{…}
6l+j c2e~+oZ7`9a o5o} JAVA中文站社区门户C!N&u&@;Z1Y^5d
JAVA中文站社区门户m:cV}2QI"W$K]
  这种实现方式基本上能够明确反映出我们对于问题领域理解正确揭示我们设计意图其 实abstract 表示是"is-a"关系erface表示是"like-a"关系大家在选择时可以作为个依据当然这是建立在对问题领域理解上比如:如果我们认为AlarmDoor在概念本质上是报警器同时又具有Door功能那么上述定义方式就要反过来了
I$A k+^6ZV,XJAVA中文站社区门户(`N J0N5T*C-Yl
  小结JAVA中文站社区门户G EUS|3v+gHG9n ?

)I1A O3[.icG  1.abstract 在 Java 语言中表示种继承关系个类只能使用次继承关系但是个类却可以实现多个erface
*xm5r%l!ov`%LJAVA中文站社区门户4xf:N GGZX"P _
  2.在abstract 中可以有自己数据成员也可以有非abstarct成员思路方法而在erface中只能够有静态不能被修改数据成员(也就是必须是 final不过在 erface中般不定义数据成员)所有成员思路方法都是abstractJAVA中文站社区门户IO"Q5tmg Yq

e(A3INkS  3.abstract erface所反映出设计理念区别其实abstract 表示是"is-a"关系erface表示是"like-a"关系 JAVA中文站社区门户X+x"b0K ~c|g'`{

n*{ l"C'rT  4.实现抽象类和接口类必须实现其中所有思路方法抽象类中可以有非抽象思路方法接口中则不能有实现思路方法JAVA中文站社区门户$G[0y5\S/j

B4?QAO  5.接口中定义变量默认是public final 型且必须给其初值所以实现类中不能重新定义也不能改变其值
D,dT2r(J&v-}JAVA中文站社区门户S"o"_Z*Oa&k
  6.抽象类中变量默认是 friendly 型其值可以在子类中重新定义也可以重新赋值
7F0@u+P$zJAVA中文站社区门户)GNW GKD~Y^z
  7.接口中思路方法默认都是 public,abstract 类型JAVA中文站社区门户(|4sW9g?J.x
JAVA中文站社区门户![ ^sd D t
  结论JAVA中文站社区门户 l\;C3?O%\ M
JAVA中文站社区门户C Tt Tr z{t
  abstract erface 是 Java语言中两种定义抽象类方式它们的间有很大相似性但是对于它们选择却又往往反映出对于问题领域中概 念本质理解、对于设计意图反映是否正确、合理它们表现了概念间区别关系(虽然都能够实现需求功能)这其实也是语言惯使用方法希望读者朋友能够细细体会


TAG: Java JAVA java 接口 解析
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: