Servlet学习笔记(五)—— java中abstract class 与 interface 的关联
2014-07-15 21:19
260 查看
一、理解抽象类
本文的抽象类并不是从abstract class翻译来的,它表示的是一个抽象体,而abstract class 是Java语言中用于定义抽象体的一种方法。在面向对象的概念中,所有的对象都是通过类来描述的,但反过来不成立:不是所有的类都是用来描绘对象的。如果一个类中没有包括足够的信息来描绘一个具体的对象,那么这样的类就是抽象类。抽象类用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是一系列看上去不同、但本质上相同的具体概念的抽象。
比如:我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形 这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题 领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。
在面向对象领域,抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行 为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。
二、抽象类与接口的区别
1.相同点:
①抽象类与接口都包含未实现的方法;②抽象类与接口都不能实例化;
③派生类都必须实现未实现的方法。
2.不同点:
首先,只有方法签名没有实现的函数叫做抽象方法。①抽象类中出了包含抽象方法,还可以有实现的方法;接口中只有抽象方法。
②抽象类中可以有自己的数据成员,可以是非公共属性的;接口中只能有常量,static final,只读不能更改,具有公共属性。
③抽象类在Java语言上表示的是一种继承关系,可以从另一个类或者一个/多个接口派生;接口不能从另外一个类派生但可以实现其他一个/多个接口。
抽象类:
abstract class A{ private int x; public abstract void doSomething(); public void test(){ System.out.println("test"); } } class B extends A{ public void doSomething(){ System.out.println("dosomething");//抽象方法的实现 } }接口:
interface A{ public static final int x=1; public abstract void doSomething(); public abstract void test(); } class B implements A{ @Override public void doSomething() { // TODO Auto-generated method stub System.out.println("dosomething"); } @Override public void test() { // TODO Auto-generated method stub System.out.println("test"); } }
三、abstract class 与 interface 的选择
很多时候我们在进行抽象类定义时对于abstract class 和interface的选择显得比较随意,上面只是从语法定义和编程的角度论述了两者的区别,是比较低层次的、非本质的。下面将从设计理念层看两者的区别,分析理解二者的概念本质所在。前面提到过,abstract class在Java语言中体现了一种继承关系,要让继承关系合理,父类和派生类之间必须存在is a 的关系,即父类和派生类在概念本质上相同的。对于interface来说则不然,并不要求interface的实现者和interface本身在概念本质上是一致的,仅仅是实现了interface定义的契约而已。下面通过一个例子来理解:
假设我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class 或者 interface来定义一个表示该抽象概念的类型,定义方式分别如下:
//abstract class 方式定义: abstract class Door { abstract public void open(); abstract public void close(); }
//interface方式定义: interface Door{ abstract public void open(); abstract public void close(); }
其他具体的Door类型可以extends使用abstract class方式定义或者implements使用interface方式定义。看起来好像没什么区别。
如果现在要求Door还要具有报警的功能,我们该如何设计针对该例子的类结构呢?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。
【解决方案一】:
//简单地在Door定义中增加一个alarm的方法 abstract class Door{ abstract void open(); abstract void close(); abstract void alarm(); }或者
//简单地在Door定义中增加一个alarm的方法: interface Door{ abstract public void open(); abstract public void close(); abstract public void alarm(); }
那么具有报警功能的AlarmDoor的定义方式如下:
<pre name="code" class="java">class AlarmDoor extents 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 class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定
义。如下所示:
abstract class Door{ abstract void open(); abstract void close(); abstract void alarm(); } interface Alarm{ void alarm(); } class AlarmDoor extends Door implements Alarm { void open(){ //... } void close(){ //... } void alarm(){ //... } }这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计 意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有 Door的功能,那么上述的定义方式就要反过来了。
【 总结 】:
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现。
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
7、抽象类里可以没有抽象方法
8、如果一个类里有抽象方法,那么这个类只能是抽象类
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、接口可继承接口,并可多继承接口,但类只能单根继承。
四、为何要引入接口
看到论坛里有一个很有意思的回答:为什么电脑主板上还要有内存插槽,显卡插槽?多浪费机箱空间啊? 直接用电烙铁把显卡和内存的引脚一根一根焊到主板上不就得了。 如果你焊错位置了,说明你焊工不好。 每次拆装的的时候再继续用电烙铁。
接口编程的直接好处就是:实现多态,同一个接口,却可以调用不同的底层实现。
五、接口的用法
六、为什么接口中不允许定义变量?
相关文章推荐
- java设计中深入理解abstract class和interface之间的关系
- java中的abstract class和interface(1)
- java中interface和abstract class
- Java 中abstract class 与 interface 的区别
- class,abstract class,interface之间的继承与实现关系(java,c#)
- java中的abstract class和interface (zz from itpub)
- java abstract class和interface有什么区别
- 深入理解java abstract class和interface[ZT]
- 详细解析Java中抽象类和接口的区别 abstract class和interface(转)
- Java 中abstract class 与 interface 的区别
- java中的abstract class和interface(2)
- 深入理解Java语言的abstract class和interface
- 【转】java abstract class 和 interface的概念分析与理解
- java 的interface和abstract class
- 在Java和C#中,abstract class和interface的区别
- java中的abstract class和interface
- java中的abstract class和interface
- java中的abstract class和interface
- 总结java的interface和abstract class
- Java中abstract class 和 interface 的解释和他们的异同点(转)