前往顾页
以后地位: 主页 > 收集编程 > Jsp实例教程 >

Java笼统类和接口的对比

时候:2011-07-14 17:02来源:知行网www.zhixing123.cn 编辑:麦田守望者

abstractclass和interface是Java说话中对笼统类定义进行支撑的两种机制,恰是因为这两种机制的存在,才付与了Java强年夜的面向工具才气。abstractclass和interface之间在对笼统类定义的支撑方面具有很年夜的类似性,乃至可以相互替代,是以很多开辟者在进行笼统类定义时对abstractclass和interface的挑选显得比较随便。其实,二者之间还是有很年夜的辨别的,对它们的挑选乃至反应出对问题范畴本质的了解、对设想企图的了解是不是精确、公道。本文将对它们之间的辨别进行一番分解,试图给开辟者供应一个在二者之间进行挑选的根据。

了解笼统类

abstractclass和interface在Java说话中都是用来进行笼统类(本文中的笼统类并不是从abstractclass翻译而来,它表示的是一个笼统体,而abstractclass为Java说话顶用于定义笼统类的一种体例,请读者重视辨别)定义的,那么甚么是笼统类,利用笼统类能为我们带来甚么好处呢?

在面向工具的观点中,我们晓得所有的工具都是经由过程类来描画的,但是反过去却不是如许。其实不是所有的类都是用来描画工具的,如果一个类中没有包含充足的信息来描画一个详细的工具,如许的类就是笼统类。笼统类常常用来表征我们在对问题范畴进行阐发、设想中得出的笼统观点,是对一系列看上去不合,但是本质上不异的详细观点的笼统。比如:如果我们进行一个图形编辑软件的开辟,就会发明问题范畴存在着圆、三角形如许一些详细观点,它们是不合的,但是它们又都属于形状如许一个观点,形状这个观点在问题范畴是不存在的,它就是一个笼统观点。恰是因为笼统的观点在问题范畴没有对应的详细观点,所以用以表征笼统观点的笼统类是不克不及够实例化的。

在面向工具范畴,笼统类首要用来进行范例埋没。我们可以机关出一个牢固的一组行动的笼统描述,但是这组行动却可以或许有肆意个可能的详细实现体例。这个笼统描述就是笼统类,而这一组肆意个可能的详细实现则表示为所有可能的派生类。模块可以操纵一个笼统体。因为模块依靠于一个牢固的笼统体,是以它可所以不许可点窜的;同时,经由过程从这个笼统体派生,也可扩展此模块的行动服从。熟谙OCP的读者必然晓得,为了可以或许实现面向工具设想的一个最核心的准绳OCP(Open-ClosedPrinciple),笼统类是此中的关头地点。

从语法定义层面看abstractclass和interface

在语法层面,Java说话对abstractclass和interface给出了不合的定义体例,下面以定义一个名为Demo的笼统类为例来讲明这类不合。

利用abstractclass的编制定义Demo笼统类的体例以下:

abstractclassDemo{

abstractvoidmethod1();

abstractvoidmethod2();

利用interface的编制定义Demo笼统类的体例以下:

interfaceDemo{

voidmethod1();

voidmethod2();

}

在abstractclass体例中,Demo可以有本身的数据成员,也能够有非 abstarct的成员体例,而在interface体例的实现中,Demo只可以或许有静态的不克不及被点窜的数据成员(也就是必须是staticfinal 的,不过在interface中一般不定义数据成员),所有的成员体例都是abstract的。从某种意义上说,interface是一种特别情势的 abstractclass。

从编程的角度来看,abstractclass和interface都可以用来实现"designbycontract"的思惟。但是在详细的利用下面还是有一些辨别的。

起首,abstractclass在Java说话中表示的是一种继承关系,一个类只能利用一次继承关系。但是,一个类却可以实现多个interface。或许,这是Java说话的设想者在考虑Java对多重继承的支撑方面的一种折中考虑吧。

其次,在abstractclass的定义中,我们可以付与体例的默许行动。但是在interface的定义中,体例却不克不及具有默许行动,为了绕过这个限定,必须利用拜托,但是这会增加一些复杂性,偶然会造成很年夜的费事。

在笼统类中不克不及定义默许行动还存在另外一个比较严峻的问题,那就是可能会造成保护上的费事。因为如果后来想点窜类的界面(一般经由过程abstractclass或interface来表示)以适应新的环境(比如,增加新的体例或给已用的体例中增加新的参数)时,就会非常的费事,可能要破钞很多的时候(对派生类很多的环境,尤其如此)。但是如果界面是经由过程abstractclass来实现的,那么可能就只需求点窜定义在abstractclass中的默许行动便可以了。

一样,如果不克不及在笼统类中定义默许行动,就会导致一样的体例实现呈现在该笼统类的每个派生类中,违背了"onerule,oneplace"准绳,造成代码反复,一样倒霉于今后的保护。是以,在abstractclass和interface间进行挑选时要非常的小心。

从设想理念层面看abstractclass和interface

下面首要从语法定义和编程的角度阐述了abstractclass和interface的辨别,这些层面的辨别是比较低层次的、非本质的。本小节将从另外一个层面:abstractclass和interface所反应出的设想理念,来阐发一下二者的辨别。作者以为,从这个层面进行阐发才气了解二者观点的本质地点。

前面已提到过,abstarctclass在Java说话中表现了一种继承关系,要想使得继承关系公道,父类和派生类之间必须存在"isa"关系,即父类和派生类在观点本质上应当是不异的(参考文献〔3〕中有关于"isa"关系的年夜篇幅深切的阐述,有兴趣的读者可以参考)。对interface来讲则不然,其实不请求interface的实现者和interface定义在观点本质上是分歧的,仅仅是实现了interface定义的左券罢了。为了使阐述便于了解,下面将经由过程一个简朴的实例进行申明。

考虑如许一个例子,假定在我们的问题范畴中有一个关于Door的笼统观点,该Door具有履行两个行动open和close,此时我们可以经由过程abstractclass或interface来定义一个表示该笼统观点的范例,定义体例别离以下所示:

利用abstractclass编制定义Door:

abstractclassDoor{

abstractvoidopen();

abstractvoidclose();

}

利用interface编制定义Door:

interfaceDoor{

voidopen();

voidclose();

}

其他详细的Door范例可以extends利用abstractclass编制定义的Door或implements利用interface编制定义的Door。看起来仿佛利用abstractclass和interface没丰年夜的辨别。

 

如果现在请求Door还要具有报警的服从。我们该若何设想针对该例子的类布局呢(在本例中,主如果为了揭示abstractclass和interface反应在设想理念上的辨别,其他方面无关的问题都做了简化或忽视)?下面将枚举出可能的处理计划,并从设想理念层面对这些不合的计划进行阐发。

处理计划一:

简朴的在Door的定义中增加一个alarm体例,以下:

abstractclassDoor{

abstractvoidopen();

abstractvoidclose();

abstractvoidalarm();

}

interfaceDoor{

voidopen();

voidclose();

voidalarm();

}

那么具有报警服从的AlarmDoor的定义体例以下:

classAlarmDoorextendsDoor{

voidopen(){…}

voidclose(){…}

voidalarm(){…}

}

classAlarmDoorimplementsDoor{

voidopen(){…}

voidclose(){…}

voidalarm(){…}

这类体例违背了面向工具设想中的一个核心准绳ISP (InterfaceSegregationPriciple),在Door的定义中把Door观点本身固有的行动体例和别的一个观点"报警器"的行动体例混在了一路。如许引发的一个问题是那些仅仅依靠于Door这个观点的模块会因为"报警器"这个观点的改变(比如:点窜alarm体例的参数)而改变,反之仍然。

处理计划二:

既然open、close和alarm属于两个不合的观点,按照ISP准绳应当把它们别离定义在代表这两个观点的笼统类中。定义体例有:这两个观点都利用abstractclass编制定义;两个观点都利用interface编制定义;一个观点利用abstractclass编制定义,另外一个观点利用interface编制定义。

明显,因为Java说话不支撑多重继承,所以两个观点都利用abstractclass编制定义是不成行的。前面两种体例都是可行的,但是对它们的挑选却反应出对问题范畴中的观点本质的了解、对设想企图的反应是不是精确、公道。我们一一来阐发、申明。

如果两个观点都利用interface体例来定义,那么就反应出两个问题:1、我们可能没有了解清楚问题范畴,AlarmDoor在观点本质上究竟是Door还是报警器?2、如果我们对问题范畴的了解没有问题,比如:我们经由过程对问题范畴的阐发发明AlarmDoor在观点本质上和Door是分歧的,那么我们在实现时就没有可以或许精确的揭露我们的设想企图,因为在这两个观点的定义上(均利用 interface编制定义)反应不出上述含义。

如果我们对问题范畴的了解是:AlarmDoor在观点本质上是Door,同时它有具有报警的服从。我们该若何来设想、实现来明白的反应出我们的意义呢?前面已说过,abstractclass在Java说话中表示一种继承关系,而继承关系在本质上是"isa"关系。所以对Door这个观点,我们应当利用abstarctclass体例来定义。别的,AlarmDoor又具有报警服从,申明它又可以或许完成报警观点中定义的行动,所以报警观点可以经由过程interface编制定义。以下所示:

abstractclassDoor{

abstractvoidopen();

abstractvoidclose();

}

interfaceAlarm{

voidalarm();

}

classAlarmDoorextendsDoorimplementsAlarm{

voidopen(){…}

voidclose(){…}

voidalarm(){…}

}

这类实现体例根基上可以或许明白的反应出我们对问题范畴的了解,精确的揭露我们的设想企图。其实abstractclass表示的是"isa"关系,interface表示的是"likea"关系,年夜家在挑选时可以作为一个根据,当然这是建立在对问题范畴的了解上的,比如:如果我们以为AlarmDoor在观点本质上是报警器,同时又具有Door的服从,那么上述的定义体例就要反过去了。

------分开线----------------------------
标签(Tag):Java JAVA实例教程 JAVA根本教程 Java源代码
------分开线----------------------------
保举内容
猜你感兴趣