一.概述


二.抽象类 abstract class

abstract viod method();

在《JAVA编程思想》一书中,将抽象类定义为“包含抽象方法的类”,但是后面发现如果一个类不包含抽象方法,只是用abstract修饰的话也是抽象类。对于这句话,首先这是对抽象类定义的一种补充,但是一个不包含抽象方法的抽象类其实没有任何实际意义(或者说有我并不知道)。就如同烂尾楼,没窗户没门,没法住人,只有个架子,但它的确是楼。


public abstract class className(){
abstract void method1();
abstract void method2();
}


抽象类需要继承,而且是单一继承,不能实例化。

(很多人不理解为什么抽象类要单一继承,我想应该是出于数据安全的考虑)


      在使用抽象类时需要注意几点:

就是不能用new操作new一个新的抽象对象,如Calendar c = new Calendar();)

三.接口 interface

接口不是类,用于多重继承,不能实例化。

public interface interfaceName(){
}


在使用接口过程中需要注意几点:

    2.接口只能包含static final的成员变量,不过在interface中一般不定义成员变量。而成员方法在接口里只能是抽象方法,访问权限只能是public。可以通过类命名直接访问:implementClass.name.(用private修饰会报编译错误)

四.接口和抽象类的区别

(下面这段话取自xw13106209,,没想到什么更好的表达方式。)

(就是interface中只能定义方法而不能有方法的实现,而在abstract class中则可以既有方法具体实现,又有没具体实现的抽象方法)。这是java抽象类的优点。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都会得到这个新方法,而java接口无法做到这点。如果向java接口里加入一个新方法,所有实现这个接口的类就无法成功通过编译,因为你必须让每一个类都再实现这个方法才行。这显然是java接口的缺点。在新的mapreduce api中更倾向于使用抽象类,而不是接口,因为更容易扩展。

“缺省适配模式”。在java语音API中用了这种模式,而且全都遵循一定的命名规范:Abstract+接口名。(A extends abstract B implements interface C,那么A既可以选择实现(@Override)接口interface C中的方法也可以选择不实现;A既可以选择实现(@Override)抽象类abstract B中的方法,也可以选择不实现)(如果有不清楚可以查看最后的例子)      

     java接口和java抽象类的存在就是为了用于具体类的实现和继承的,如果你准备写一个具体类去继承另一个具体类的话,那你的设计就有很大问题。java抽象类就是为了继承而存在的,它的抽象方法就是为了强制子类必须去实现的。
等。

    1.语法上的区别:
java语言对于抽象类和接口分别给出了不同的定义。下面通过Demo类来说明他们之间的不同之处。
抽象类:

public abstract class Demo {    
    abstract void method1();    
        
    void method2(){    
        //实现    
    }    
}


接口:


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

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

    1)abstract class表示的是继承关系,但一个类却可以实现多个接口(这应该是java语言设计者在考虑java对于多重继承的一种折中考虑。) 

    2)在abstract class中我们可以赋予方法默认行为,但在interface的定义中,方法不能拥有默认行为。(不能定义默认行为会导致一个问题,那就是在修改接口的界面的时候会导致维护上的麻烦,比如添加新的方法或者新的参数时,特别是派生类多的时候需要花费大量的时间,但是如果是抽象类,可能只修改定义在abstract class中的默认行为就可以了)
    3)同2,如果不在抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了"one rule,one place"原则,造成代码重复,不利于以后的维护。2.设计层面区别:
    接口与抽象类在使用方式上有相同之处,但在设计目的上有巨大差别。
    1)接口作为系统和外界的交互窗口,体现的是一种规范。对于接口的实现者而言,接口规定了实现者必须向外提供哪些服务(以方法的形式),对于接口的调用者而言,接口规定了调用者可以调用哪些服务,以及如何调用。
接口是辐射式设计,就好比大多数网游的版本,一旦服务器版本升级,所有用户都得升级,否则没法进入游戏 。所以一个系统中接口不应该轻易改变,否则对整个系统甚至其他系统的影响是辐射性的,导致其派生类都需要重写。
   2)抽象类与接口不同,抽象类作为系统中多个子类的共同父类,它属于模板式设计。就比如A,B页面通过<iframe src="C.html" ></iframe>变成了两个不同的页面,C是公共部分,当需要更改公共部分时,只需要改C就可以了,不需要改动A和B.(总觉得哪里别扭,但是意思没问题)所以如果需要添加新方法,直接在抽象类中添加具体实现,而子类不需要更改。


    2)在abstract class中我们可以赋予方法默认行为,但在interface的定义中,方法不能拥有默认行为。(不能定义默认行为会导致一个问题,那就是在修改接口的界面的时候会导致维护上的麻烦,比如添加新的方法或者新的参数时,特别是派生类多的时候需要花费大量的时间,但是如果是抽象类,可能只修改定义在abstract class中的默认行为就可以了)

    3)同2,如果不在抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了"one rule,one place"原则,造成代码重复,不利于以后的维护。2.设计层面区别:

    接口与抽象类在使用方式上有相同之处,但在设计目的上有巨大差别。

    1)接口作为系统和外界的交互窗口,体现的是一种规范。对于接口的实现者而言,接口规定了实现者必须向外提供哪些服务(以方法的形式),对于接口的调用者而言,接口规定了调用者可以调用哪些服务,以及如何调用。

接口是辐射式设计,就好比大多数网游的版本,一旦服务器版本升级,所有用户都得升级,否则没法进入游戏 。所以一个系统中接口不应该轻易改变,否则对整个系统甚至其他系统的影响是辐射性的,导致其派生类都需要重写。


   2)抽象类与接口不同,抽象类作为系统中多个子类的共同父类,它属于模板式设计。就比如A,B页面通过<iframe src="C.html" ></iframe>变成了两个不同的页面,C是公共部分,当需要更改公共部分时,只需要改C就可以了,不需要改动A和B.(总觉得哪里别扭,但是意思没问题)所以如果需要添加新方法,直接在抽象类中添加具体实现,而子类不需要更改。

   1)接口里不能定义静态方法;抽象类里可以定义静态方法。

   2)接口里不包含构造器,抽象类可以包含构造器,抽象类里的构造器并不是用于创作对象,而是让其子类调用这些构造器来完成属于抽象类的初始化方法。

   3)接口里不能包含初始化块,但抽象类可以包含初始化块。

   4)接口里只能定义静态常量,不能定义其他变量。抽象类既可以定义普通变量,也可以定义静态常量。

   5)接口里不能包含已经提供实现的方法,只能包含抽象方法;抽象类可以包含普通方法。

最后找一个网上多用的例子,门和报警:门都有open()和close()两个动作,此时我们可以通过定义抽象类和接口来定义这个抽象概念:

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



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

    现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?下面提供两种思路:

    1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门不一定需要具有报警功能。

    2)将这三个功能都放在接口里面,需要用的报警功能的类就需要实现这个接口中的open()和close(),或许这个类并不具备open()和close()这两个功能,比如火灾报警器。

    从这里可以看出,Door的open(),close()和alarm()属于两个不同范畴内的行为,open()和close()属于门本身的固有行为特性。而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含Alarm()行为,而Door设计为一个抽象类,包含open()和close()两种行为。再设计一个报警门继承Door类和实现Alarm接口。(其实这就是上面引用文字中提到的“缺省适配模式”)


interface Alram {
    void alarm();
}
 
abstract class Door {
    void open();
    void close();
}
 
class AlarmDoor extends Door implements Alarm {
    void oepn() {
      //....
    }
    void close() {
      //....
    }
    void alarm() {
      //....
    }
}