Java中抽象类与接口的区别
抽象类和接口是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。抽象类和接口之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进行抽象类定义时对于抽象类和接口的选择显得比较随意。其实,两者之间还是有很大的区别的,那么它们之间有什么区别呢?下面,学习啦小编带你去了解一下。
一、抽象类与接口语法定义的区别
在语法层面,Java语言对于抽象类和接口给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。
使用抽象类的方式定义Demo抽象类的方式如下:
abstract class Demo {
abstract void method1();
abstract void method2();
…
}
使用interface的方式定义Demo抽象类的方式如下:
interface Demo {
void method1();
void method2();
…
}
在抽象类方式中,Demo可以有自己的数据成员,也可以有非abstarct的成员方法。
而在接口方式的实现中,Demo只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。
从某种意义上说,接口是一种特殊形式的抽象类。
二、抽象类和接口的编程区别
从编程的角度来看,抽象类和接口都可以用来实现"design by contract"的思想。但是在具体的使用上面还是有一些区别的。
1、抽象类在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。
但是,一个类却可以实现多个接口。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。
2、在抽象类的定义中,我们可以赋予方法的默认行为。
但是在接口的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会 增加一些复杂性,有时会造成很大的麻烦。
3.在抽象类中定义默认行为,一旦抽象类中的行为方法发生改变,就会影响继承他的子类。
但是另一个方面,如果不利用抽象类中定义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了"one rule,one place"原则,造成代码重复,同样不利于以后的维护。
因此,在抽象类和接口间进行选择时要非常的小心。
三、抽象类和接口的设计理念区别
上面主要从语法定义和编程的角度论述了抽象类和接口的区别,这些层面的区别是比较低层次的、非本质的。现在小编将从另一个层面,即抽象类和接口所反映出的设计理念,来分析一下二者的区别。小编认为,从这个层面进行分析才能理解二者概念的本质所在。
抽象类在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的(参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述,有兴趣的读者可以参考)。
对于接口来说则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。
考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过抽象类或者接口来定义一个表示该抽象概念的类型,定义方式分别如下所示:
使用抽象类方式定义Door:
abstract class Door {
abstract void open();
abstract void close();
}
使用接口方式定义Door:
interface Door {
void open();
void close();
}
其他具体的Door类型可以extends使用抽象类方式定义的Door或者implements使用接口方式定义的Door。看起来好像使用抽象类和接口没有大的区别。