java的抽象类和接口
什么是java的抽象类和接口?
abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。 在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是 这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领 域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。而接口呢,它则是一组规则的集合,它规定了实现本接口的类必须拥有的一组规则。体现了自然界“如果你是……则必须能……”的理念。下面详细分析抽象类和接口以及它们之间的区别。
抽象类和接口的区别和联系?
语法层面上的区别:
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
跨域层面上的区别:
抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is-a” 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的, 仅仅是实现了接口定义的契约而已。抽象类所跨域的是具有相似特点的类,而接口却可以跨域不同的类。
设计层面上的区别:
抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。从动机角度,使用抽象类是很好的解决了代码的复用,而使用接口的却实现了多态性。
设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。
考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:
|
|
|
|
其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢?
方案一:
简单的在Door的定义中增加一个alarm方法。
对于抽象类,所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能。
对于接口,需要用到报警功能的类就需要实现这个接口中的open( )和close( ),也许这个类根本就不具备open( )和close( )这两个功能,比如火灾报警器。
|
|
|
|
也就是说这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念”报警器”的行为方法混在了一起。
ISP(Interface Segregation Principle):面向对象的一个核心原则。它表明使用多个专门的接口比使用单一的总接口要好。
一个类对另外一个类的依赖性应当是建立在最小的接口上的。
一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。
方案二:
既然open()、close()和alarm()属于两个不同的概念,那么我们依据ISP原则将它们分开定义在两个代表两个不同概念的抽象类里面,一个使用抽象类定义,一个是用接口定义。
|
|
|
|
|
|
抽象类和接口使用注意?
抽象类使用之前需要注意:
抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。
抽象方法必须由子类来进行重写,同时必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;。
只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。
抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
子类中的抽象方法不能与父类的抽象方法同名。
abstract不能与final并列修饰同一个类。
abstract 不能与private、static、final或native并列修饰同一个方法。
接口使用之前需要注意:
接口的所有方法的访问权限自动被声明为public,而且只能是public。
接口中可以定义“成员变量”,或者说是不可变的常量,因为接口中的“成员变量”会自动变为为public static final。可以通过类命名直接访问:ImplementClass.name。
接口中不存在实现的方法。
实现接口的非抽象类必须要实现该接口的所有方法。抽象类可以不用实现。
不能使用new操作符实例化一个接口,但可以声明一个接口变量,该变量必须引用(refer to)一个实现该接口的类的对象。可以使用 instanceof 检查一个对象是否实现了某个特定的接口。例如:if( anObject instanceof Comparable) {}。
在实现多接口的时候一定要避免方法名的重复。
抽象类的特殊使用?
抽象类使用static注意事项:
1.关于外部抽象类不能声明为static,例如将上述的Employee改为public static abstract class Employee {…},会报Illegal modifier for the class Employee; only public, abstract & final are permitted,但是内部抽象类可以。
|
|
|
|
|
|
2.可以直接调用抽象类中用static声明的方法,就像普通类一样。
3.利用抽象类对用户隐藏不需要知道的子类。
|
|
|
|
抽象类常规示例:
|
|
|
|
|
|
Java8的接口新特性?
静态方法
static定义的方法用接口名调用
默认方法
default定义的普通方法用对象调用
|
|
|
|
参考:
http://blog.csdn.net/wenwen091100304/article/details/48381023