`

Java接口Interface与抽象类Abstract Class

    博客分类:
  • Java
阅读更多

一. 面向接口编程

      在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的对系统设计人员来讲就不 那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统 设计的主要工作内容。面向接口编程我想就是指按照这种思想来编程吧!实际上,在日常工作中,你已经按照接口编程了,只不过如果你没有这方面的意识,那么你 只是在被动的实现这一思想;表现在频繁的抱怨别人改的代码影响了你(接口没有设计到),表现在某个模块的改动引起其他模块的大规模调整(模块接口没有很好 的设计)等等。
      Booch先生那天谈到Interaction Designer,它就是指做这类设计的人,只不过层次更高一些。我想目前我们的软件设计队伍中,这类人是最缺乏的人才之一。
      非接口编程是不是就是面向过程的编程思想?
      1.关于接口的理解
      接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。我们在一般实现一个系统的时候,通常是将定义与实现合为一体,不加分离的。实际上,系统设计规范应是所有的定义与实现分离,尽管这可能对系统中的某些情况有点繁烦。
      接口的本身反映了系统设计人员对系统的抽象理解。
      接口应有两类:第一类是对一个体的抽象,它可对应为一个抽象体(abstract class);第二类是对一个体某一方面的抽象,即形成一个抽象面(interface)。 一个体有可能有多个抽象面,抽象体与抽象面是有区别的。
       2.设计接口的另一个不可忽视的因素是接口所处的环境(context,environment)
       系统论的观点:环境是系统要素所处的空间 与外部影响因素的总和。任何接口都是在一定的环境中产生的。因此环境的定义及环境的变化对接口的影响是不容忽视的,脱离原先的环境,所有的接口将失去原有 的意义。
       3.按照组件的开发模型(3C),它们三者相辅相成,各司一面,浑然一体,缺一不可
       面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法;面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现;接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题。
        UML里面所说的interface是协议的另一种说法,并不是指COM的interface,CORBA的interface,Java的 interface,Delphi的interface,人机界面的interface或NIC的interface。
        在具体实现中,是可以把UML的interface实现为语言的interface,分布式对象环境的interface或其它什么 interface,但就理解UML的interface而言,指的是系统每部分的实现和实现之间,通过interface所确定的协议来共同工作。
        面向interface编程,原意是指面向抽象协议编程,实现者在实现时要严格按协议来办。也就是BillJoy同志说的,一边 翻rfc,一边写代码的意思。面向对象编程是指面向抽象和具象。抽象和具象是矛盾的统一体,不可能只有抽象没有具象。一般懂得抽象的人都明白这个道理。 但有的人只知具象却不知抽象为何物。所以只有interface没有实现,或只有实现而没有interface者是没有用的,反OO的。
二.选择Java接口还是抽象类
       很多人有过这样的疑问:为什么有的地方必须使用接口而不是抽象类,而在另一些地方,又必须使用抽象类而不是接口呢?或者说,在考虑Java类的一般化问题时,很多人会在接口和抽象类之间犹豫不决,甚至随便选择一种。
       实际上接口和抽象类的选择不是随心所欲的。要理解接口和抽象类的选择原则,有两个概念很重要:对象的行为和对象的实现。如果一个实体可以有多 种实现方式,则在设计实体行为的描述方式时,应当达到这样一个目标:在使用实体的时候,无需详细了解实体行为的实现方式。也就是说,要把对象的行为和对象 的实现分离开来。既然Java的接口和抽象类都可以定义不提供具体实现的方法,在分离对象的行为和对象的实现时,到底应该使用接口还是使用抽象类呢?
      1.通过抽象类建立行为模型
      在接口和抽象类的选择上,必须遵守这样一个原则:行为模型应该总是通过接口而不是抽象类定义。为了说明其原因,下面试着通过抽象类建立行为模型,看看会出现什么问题。
      假设要为销售部门设计一个软件,这个软件包含一个“发动机”(Motor)实体。显然无法在发动机对象中详细地描述发动机的方方面面,只能描述某些对当前软件来说重要的特征。至于发动机的哪些特征是重要的,则要与用户(销售部门)交流才能确定。
      销售部门的人要求每一个发动机都有一个称为马力的参数。对于他们来说,这是惟一值得关心的参数。基于这一判断,可以把发动机的行为定义为以下行为:
      行为1:查询发动机的马力,发动机将返回一个表示马力的整数。
      虽然现在还不清楚发动机如何取得马力这个参数,但可以肯定发动机一定支持这个行为,而且这是所有发动机惟一值得关注的行为特征。这个行为特征 既可以用接口定义,也可以用抽象类定义。为了说明用抽象类定义可能出现的问题,下面用抽象类建立发动机的行为模型,并用Java方法描述行为1,代码如 下:

public abstract Motor
{              
     abstract public int getHorsepower();              
}  

       在Motor抽象类的基础上构造出多种具体实现,例如A型发动机、B型发动机等,再加上系统的其它部分,最后得到1.0版的软件并交付使用。 一段时间过去了,现在要设计2.0版的软件。在评估2.0版软件需求的过程中,发现一小部分发动机是电池驱动的,而电池需要一定的充电时间。销售部门的人 希望能够通过计算机查阅充电时间。根据这一要求定义一个新的行为,如图1所示。
       行为2:查询电驱动发动机的充电时间,发动机将返回一个表示充电时间的整数。
       用Java方法来描述这个行为,代码如下:

public abstract BatteryPoweredMotor extends Motor
{             
      abstract public int getTimeToRecharge();            
} 

       在销售部门的软件中,电驱动发动机也以类的形式实现,但这些类从BatteryPoweredMotor而不是Motor派生。这些改动加入到2.0版软 件之后,销售部门很满意。随着业务的不断发展,不久之后光驱动的发动机出现了。销售部门要求光驱动发动机需要一定光能才能运转,光能以流明(Lumen) 度量。这个信息对客户很重要,因为下雨或多云的天气里,某些光驱动发动机可能无法运转。销售部门要求为软件增加对光驱动发动机的支持,所以要定义一个新的 行为。
      行为3:查询光驱动发动机能够正常运转所需要的最小流明数,发动机返回一个整数。
      再定义一个抽象类并把行为3转换成Java方法,代码如下:

public abstract SolarPoweredMotor extends Motor
{              
      abstract public int getLumensToOperate();            
}

       如图1所示,SolarPoweredMotor和BatteryPoweredMotor都从Motor抽象类派生。在整个软件中,90% 以上的代码以相同的方式对待所有的发动机。偶尔需要检查一下发动机是光驱动还是电驱动,使用instanceof实现,代码如下:

if (instanceof SolarPoweredMotor){...}         
     if (instanceof BatteryPoweredMotor){...} 

      无论是哪种发动机,马力这个参数都很重要,所以在所有派生的抽象类(SolarPoweredMotor和BatteryPoweredMotor)中,getHorsepower()方法都有效。
      现在销售部门又有了一种新的发动机,它是一种既有电驱动又有光驱动的双重驱动发动机。光驱动和电驱动的行为本身没有变化,但新的发动机同时支持两种行为。 在考虑如何定义新型的光电驱动发动机时,接口和抽象类的差别开始显示出来了。新的目标是在增加新型发动机的前提下尽量少改动代码。因为与光驱动发动机、电 驱动发动机有关的代码已经过全面的测试,不存在已知的Bug。为了增加光电驱动发动机,要定义一个新的 SolarBatteryPowered抽象类。如果让SolarBatteryPowered从Motor抽象类派 生,SolarBatteryPowered将不支持针对光驱动发动机和电驱动发动机的instanceof操作。也就是说,如果查询一个光电驱动的发动 机是光驱动的,还是电驱动的,得到的答案是:都不是。
      如果让SolarBatteryPowered从SolarPoweredMotor(或BatteryPoweredMotor)抽象类派生,类似的问 题也会出现,SolarBatteryPowered将不支持针对BatteryPoweredMotor(或 SolarPoweredMotor)的instanceof操作。从行为上看,光电驱动的发动机必须同时从两个抽象类派生,但Java语言不允许多重继 承。之所以会出现这个问题,根本的原因在于使用抽象类不仅意味着定义特定的行为,而且意味着定义实现的模式。也就是说,应该定义一个发动机如何获得行为的 模型,而不仅仅是声明发动机具有某一个行为。

     2.通过接口建立行为模型
     如果用接口来建立行为模型,就可以避免隐含地规定实现模式。例如,前面的几个行为改用接口定义如下:
     行为1的Java代码:

public interface Motor()
{            
     public int getHorsepower();            
} 

     行为2的Java代码:

public interface BatteryPoweredMotor extends Motor()
{             
      public int getTimeToRecharge();            
}

     行为3的Java代码:

public interface SolarPoweredMotor extends Motor
{             
     abstract public int getLumensToOperate();            
}  

      现在光电驱动的发动机可以描述为:

      public  DualPoweredMotor  implements  SolarPoweredMotor, BatteryPoweredMotor{}              

      DualPoweredMotor只继承行为定义,而不是行为的实现模式,如图2所示。
      在使用接口的同时仍旧可以使用抽象类,不过这时抽象类的作用是实现行为,而不是定义行为。只要实现行为的类遵从接口定义,即使它改变了父抽象类,也不用改 变其它代码与之交互的方式。特别是对于公用的实现代码,抽象类有它的优点。抽象类能够保证实现的层次关系,避免代码重复。然而,即使在使用抽象类的场合, 也不要忽视通过接口定义行为模型的原则。从实践的角度来看,如果依赖于抽象类来定义行为,往往导致过于复杂的继承关系,而通过接口定义行为能 够更有效地分离行为与实现,为代码的维护和修改带来方便。

三. Java接口特性学习
       在Java中看到接口,第一个想到的可能就是C++中的多重继承和Java中的另外一个关键字abstract。从另外一个角度实现多重继承是接口的功能 之一,接口的存在可以使Java中的对象可以向上转型为多个基类型,并且和抽象类一样可以防止他人创建该类的对象,因为接口不允许创建对象。
       interface关键字用来声明一个接口,它可以产生一个完全抽象的类,并且不提供任何具体实现。interface的特性整理如下:

       1.接口中的方法可以有参数列表和返回类型,但不能有任何方法体。
       2.接口中可以包含字段,但是会被隐式的声明为static和final。
       3.接口中的字段只是被存储在该接口的静态存储区域内,而不属于该接口。
       4.接口中的方法可以被声明为public或不声明,但结果都会按照public类型处理。
       5.当实现一个接口时,需要将被定义的方法声明为public类型的,否则为默认访问类型,Java编译器不允许这种情况。
       6.如果没有实现接口中所有方法,那么创建的仍然是一个接口。
       7.扩展一个接口来生成新的接口应使用关键字extends,实现一个接口使用implements。
       interface在某些地方和abstract有相似的地方,但是采用哪种方式来声明类主要参照以下两点:
       1.如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。
       2.如果知道某个类应该是基类,那么第一个选择的应该是让它成为一个接口,只有在必须要有方法定义和成员变量的时候,才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法,只要方法没有被全部实现该类就仍是抽象类。
       以上就是接口的基本特性和应用的领域,但是接口绝不仅仅如此,在Java语法结构中,接口可以被嵌套,既可以被某个类嵌套,也可以被接口嵌套。这 在实际开发中可能应用的不多,但也是它的特性之一。需要注意的是,在实现某个接口时,并不需要实现嵌套在其内部的任何接口,而且,private接口不能 在定义它的类之外被实现。

分享到:
评论

相关推荐

    Java中抽象类和接口的区别与作用详解

    结论:abstract class和Interface是JAVA语言中的两种定义抽象类的方式。Interface将abstract的概念作了更进一步的发挥。你可以想像Interface是“纯粹”的 abstract class,只可以包含抽象方法,也包括一些常量的定义...

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

    抽象类和接口的区别 在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。abstract class和interface之间在对于抽象类定义的支持...

    Java中抽象类和接口的区别

    在Java语言中,abstract class和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,...

    深入理解abstract class和interface

    abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性...

    Java中interface接口与abstractclas

    Java中interface接口与abstractclass抽象类的区别共2页.pdf.zip

    JAVA中抽象类和接口的区别

    在Java语言中,abstract class 和interface 是支持抽象类定义的两种机制区别

    浅析Java抽象类和接口的比较

    abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。

    JAVA中抽象类与接口的区别

    在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性...

    1.5:接口和抽象类的区别.pdf

    4.实现抽象类和接口的类必须实现其中的所有方法。 抽象类中可以有非抽象方法。接口中则不能有实现方法。如果接口或者抽象类的子类不想实现则继续携程一个抽象方法 5.接口中定义的变量默认是public static final ...

    java高级类操作 接口与抽象类的操作

    circle Rectangle等类在接口中计抽象类中的用法 抽象类 接口多态 public class Polymorphism { public static void main(String args[]) { Triangle t=new Triangle(5.0,2.0); t.show_area(); Rectangle r=...

    Java中抽象类和接口的区别.zip_java interf

    在Java语言中,abstract class和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,...

    Java学习笔记---15.面向对象编程10-Java中final关键字,抽象类与接口

    好啊好啊 抽象类与接口是Java中最重要部分之一,这里用较大的篇幅来做下这部分的笔记. 1. final关键字 在Java中, 可以使用final关键字修饰类、方法以及成员变量。 (1).final标记的类不能被继承; (2).final标记...

    C++中抽象类和接口的区别介绍

    抽象类(abstract class)和接口(interface)的概念是面向对象设计中常用的概念, 也是比较容易混淆的概念. 在这里, 我提出一种区分它们的思路

    Java接口和抽象类的特殊实现方法

    一、java中的接口本质上是加约束的抽象类 //抽象类 public abstract class AExample {  public abstract int add(int x,int y);  public abstract int sub(int x,int y); } //接口 public interface ...

    abstract class

    abstract class 抽象类--不具体的类 1) 抽象方法,只有行为的概念,没有具体的行为实现。 2) 包含抽象方法的类,就一定是抽象类。 使用: abstract 关键字修饰,包含抽象方法。 如:平面图形一定可以计算面积。 ...

    Java抽象类与接口的区别

    含有abstract修饰符的class 即为抽象类,abstract类不能创建实例对象,含有abstract的方法的类必须定义为abstract class ,abstract class 里的方法不必是抽象的,抽象类中定义抽象方法必须放在具体子类中实现,所以...

Global site tag (gtag.js) - Google Analytics