当前位置:  技术问答>java相关

JAVA里边的Interface 和 Abstract class有什么区别?

    来源: 互联网  发布时间:2015-10-26

    本文导语:  什么时候用Interface? 什么时候用Abstract class? | China    dW 中国所有内容.................dW 中国技术专区: 组件技术 Java 技术 Linux XML.................dW 中国特别专题: 安全 Unicode 网站架构...

什么时候用Interface?
什么时候用Abstract class?

|
China  
 dW 中国所有内容.................dW 中国技术专区: 组件技术 Java 技术 Linux XML.................dW 中国特别专题: 安全 Unicode 网站架构.................IBM 全部内容      
搜索帮助 
 
 
      IBM 主页   |   产品与服务   |   支持与下载   |   个性化服务 
 
 
 
 
 
 
IBM : developerWorks 中国网站 : Java : 所有的文章    
 
 
 深入理解abstract class和interface   
 
 
   
内容: 
 
理解抽象类 
从语法定义层面看abstract class和interface 
从编程层面看abstract class和interface 
从设计理念层面看abstract class和interface 
结论 
参考资料 
关于作者 
 
 
Also in the Java zone: 
 
教学 
工具与产品 
代码与组件 
所有文章 
实用技巧 
 
 
 
 
邓辉 、孙鸣 (dhui@263.net)

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

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

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

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

从语法定义层面看abstract class和interface

在语法层面,Java语言对于abstract class和interface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。

使用abstract class的方式定义Demo抽象类的方式如下:


abstract class Demo {
abstract void method1();
abstract void method2();



 


使用interface的方式定义Demo抽象类的方式如下:


interface Demo {
void method1();
void method2();

}

 


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

对于abstract class和interface在语法定义层面更多的细节问题,不是本文的重点,不再赘述,读者可以参阅参考文献〔1〕获得更多的相关内容。

从编程层面看abstract class和interface

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

首先,abstract class在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。

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

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

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

从设计理念层面看abstract class和interface

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

前面已经提到过,abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的(参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述,有兴趣的读者可以参考)。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。

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

使用abstract class方式定义Door:


abstract class Door {
abstract void open();
abstract void close();
}

 


使用interface方式定义Door:


interface Door {
void open();
void close();
}

 


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

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

解决方案一:

简单的在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() { … }


 


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

解决方案二:

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

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

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

如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报

|
发表点自己的拙见:
  接口和abstract类有很大的相似性,同样是在父类中只声明了方法头而无方法体,都要有子类来完成具体的行为,但是声明为实现接口的子类,只是从其接口父类中继承了方法的规范,而不是结构,也没有继承其成员数据字段和成员方法,而abstract 类的子类,可以继承起父类的成员方法,例如Java类库中的Number类!


|
1.他们都可以限定子类必须实现的方法。
2.Abstract class中你还可以定义属性,也可以实现部分方法,让他可以进行默认的处理,interface则只能定义一些方法的接口。所以有些框架类都是用Abstract class定义的。

|
interface内只有函数声明,没有函数实现
Abstract内一定有虚函数,也可以有实函数

|
inteferce 是用来implements的
abstractClass是用来extends的。
所以interface可以用来实现多继承。

|
你可以这样扩展一个接口
interface face1 extends face2{
 void yourMethod();
}

    
 
 

您可能感兴趣的文章:

  • java命名空间java.lang.reflect类modifier的类成员方法: interface定义及介绍
  • 关于java.util.EventObject的疑问?和abstract ,interface关键字的疑问?
  • java命名空间javax.lang.model.element枚举elementkind的类成员方法: interface定义及介绍
  • java abstract class interface之间的区别介绍
  • java命名空间javax.xml.ws.handler接口messagecontext成员方法: wsdl_interface定义参考
  • java命名空间javax.management类jmx的类成员方法: interface_class_name_field定义及介绍
  • java命名空间javax.lang.model.element枚举modifier的类成员方法: abstract定义及介绍
  • Java修饰符 abstract,static,final 的区别详解
  • java命名空间java.lang.reflect类modifier的类成员方法: abstract定义及介绍
  • java命名空间java.awt.color类icc_profile的类成员方法: class_abstract定义及介绍
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java命名空间javax.tools枚举javafileobject.kind的类成员方法: class定义及介绍
  • 有两个:1.class与2.java,2.java继承1.class类,要把2.java编译成2.class给如何书写!
  • java命名空间java.io接口objectstreamconstants的类成员方法: tc_class定义及介绍
  • xx.java继承yy.class,编译xx.java为xx.class时应怎样书写?(谢谢)
  • java命名空间java.lang.annotation枚举retentionpolicy的类成员方法: class定义及介绍
  • 我昨天刚学java用的是JBuilder可是我用F9运行之后在classes目录中生成的.class文件为什么我在用java.exe application1时出现如下的错误呢
  • java命名空间java.lang类class<t>的类成员方法: getsuperclass定义及介绍
  • java bean和java class的区别??
  • java命名空间javax.swing.text.html类html.attribute的类成员方法: class定义及介绍
  • JAVA编译的CLASS文件可以反编译为JAVA文件吗?
  • java命名空间javax.tools枚举standardlocation的类成员方法: class_path定义及介绍
  • java线程怎么调用java的application.class?
  • java命名空间javax.lang.model.element枚举elementkind的类成员方法: class定义及介绍
  • 谁有办法用java执行于java.exe不在一个目录的class文件?
  • java命名空间javax.tools枚举standardlocation的类成员方法: class_output定义及介绍
  • 用什么工具可以把JAVA的.CLASS文件反编译成.JAVA文件??
  • java命名空间java.util类resourcebundle.control的类成员方法: format_class定义及介绍
  • 在java中,什么情况下属于不同的进程,是在不同的classload中加载的class,还是在不同的jvm中加载的class
  • java命名空间java.lang类class<t>的类成员方法: getenumconstants定义及介绍
  • 请问java bean 与普通的java class的主要区别?
  • java命名空间java.lang类class<t>的类成员方法: getdeclaringclass定义及介绍
  • 我已经编译了一个hello.class的文件,为什么,使用java hello还是提示没有hello.class这个类呢?
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3