接口与抽象类
定义类的过程就是抽象和封装的过程。
而接口与抽象类则是对实体类更高层次的抽象,仅定义公共行为和特征。
共同点:都不能被实例化,但可以定义引用变量指向实例对象。
通俗的讲就是类描述的是 这个东西是什么(强调所属)包含了静态属性,静态行为 ,属性和行为。
而接口 描述的它能做什么事儿(强调行为)只是 静态常量属性 和 行为.下面从几个方面来比较下两者区别。
从语法层面来讲:
需要注意的是:
a.虽然接口的关键字是interface,但是编译之后的字节码扩展名还是.class。
b.接口被实现时体现的是:can-do的关系。要符合里氏代换原则。通常是对同类事物具体的抽象 。
c.抽象类在被继承的时候体现的是:is-a的关系。要符合接口隔离原则。
从设计层面来讲:
抽象类是模板类设计,而接口是契约式设计。
这一点具体来说的话就是,抽象类包含一组相对具体的特征。而接口是开放的,它更像一份合同,定义了方法名、参数、返回值,包括跑出的异常类型。谁都可以来实现它,如果实现了,就必须遵守这份接口合约的合同。
体系结构上的关系:
接口位于顶层,而抽象类对各个接口进行了组合,然后 实现部分接口行为。
集合框架中有一个重要的接口:Collection。而AbstractCollection则是最典型的抽象类。
package java.util;
//该抽象类是Collection的一个实现类
public abstract class AbstractCollection<E> implements Collection<E> {
protected AbstractCollection() {
}
public abstract Iterator<E> iterator();
//size()这个方法对于链表和顺序表有不同的实现方式。
// Collection接口定义的方法 ,需要不同的实现。
public abstract int size();
//AbstractCollection的子类,判空的方法是一样的。
//这就是模板设计,对于所有的子类,实现共同的方法体。
public boolean isEmpty() {
return size() == 0;
}
。。。
}
由于两者有了如此多的区别,那肯定有不同的应用场景。
抽象类的使用场景
一句话,在既需要统一的接口,又需要实例变量或缺省的方法的情况下,就可以使用它。最常见的有:
A.某些情况下,没有必要实现接口中的每一个方法。可以用abstract class定义一组方法体,甚至可以是空方法体,然后由子类选择自己所感兴趣的方法来覆盖。
B. 某些场合下,只靠纯粹的接口不能满足类与类之间的协调,还必需类中表示状态的变量来区别不同的关系。abstract的中介作用可以很好地满足这一点。
C.有些子类需要根据自己的特定状态来实现特定的功能。可以通过多态来调用到子类的具体的方法实现上(比如AbstratcCollection)。
D.如果有多个接口实现有公用的部分,则使用抽象类,然后集成它。
在纠结定义接口还是抽象类的时候,优先推荐定义接口。遵循接口隔离原则,按照某个维度划分成多个接口,然后再用抽象类去implements某些接口。不仅仅因为java采用单继承的形式,这样子可方便后续的扩展和重构。