接口的抽象类给我们提供了接口和实现分离更加结构化的方法
接口和抽象类是java中对抽象概念进行定义的两种机制,正是因为他们的存在,才赋予了java强大的面向对象的能力。他们之间对于抽象有很大的相似,但是也有一些不同
抽象类
前面我们说过万物皆对象,对象是通过类来描述的,但并不是所有的类都是用来描述对象的。如果一个类没有足够的信息来描述一个具体的对象,而需要其他具体的类来支撑它,那么这样的类我们称为抽象类。
比如new Car(),但是具体的car长什么样,我们是不知道的,是抽象类。我们需要一个具体的车,比如卡宴,宝马等进行特定描述。
抽象类体现了抽象的思想,是实现多态的一种机制,他定义了一组抽象方法,其中的具体形式通过子类来实现。抽象类会被继承,否则其没有存在的意义。使用抽象类时,需要注意以下几点:
- 抽象类不能被实体化,只需要提供一个引用就行了
- 抽象方法由子类进行重写
- 只要有一个抽象方法,这个类就是抽象类
- 子类中的抽象方法不能和父类中的抽象方法一样
- 抽象方法也可以有具体方法,可以有成员变量
- abstract修饰的方法就是需要被重写,因此不能跟static,private并列修饰一个方法
实例
定义一个动物类Aninal,提供抽象方法cry(),猫狗为子类,如下:
public abstract class Animal {
public abstract void cry();
}
public class Cat extends Animal{
@Override
public void cry() {
System.out.println("猫叫:喵喵...");
}
}
public class Dog extends Animal{
@Override
public void cry() {
System.out.println("狗叫:汪汪...");
}
}
public class Test {
public static void main(String[] args) {
Animal a1 = new Cat();
Animal a2 = new Dog();
a1.cry();
a2.cry();
}
}
--------------------------------------------------------------------
Output:
猫叫:喵喵...
狗叫:汪汪...
接口
关键字interface将abstract的概念做了更进一步的发挥,可以想象它是纯粹的abstract class,他构建出class(函数名,参数列表 返回类型)的形式,但是没有方法体。interface中可以含有数据成员,但是自然而然成为static final。interface值提供形式,不实现细节。
接口是抽象类的延伸,接口优于抽象类的一点是能够多实现,弥补了抽象类不能多继承的缺陷。在使用接口的过程中,需要注意一下问题:
- interface中的所有方法都会被自动声明为public,且只能为public
- 接口中可以声明变量,但是是静态变量
- 接口中不存在实现的方法
- 实现接口的非抽象类必须实现接口中所有的方法
- 接口不能被实例化
- 在实现多接口的时候注意避免方法名的重复
抽象类的接口的区别
1,语法层次
在语法层次,两者定义不同。下面使用代码来说明不同之处。
抽象类:
public abstract class Demo {
abstract void method1();
void method2(){
//实现
}
}
接口:
interface Demo {
void method1();
void method2();
}
抽象类方式中,抽象类可以拥有任意范围的成员数据,同时也可以拥有自己的非抽象方法,但是接口方式中,它仅能够有静态、不能修改的成员数据(但是我们一般是不会在接口中使用成员数据),同时它所有的方法都必须是抽象的。在某种程度上来说,接口是抽象类的特殊化。
对子类而言,它只能继承一个抽象类(这是java为了数据安全而考虑的),但是却可以实现多个接口。
2,设计层次
从设计层次上来讲,才能看出两者本质的差别
1,抽象层次不同。抽象类时对类抽象,接口是对行为的抽象。抽象类时是对类整体抽象,包括行为属性,但是interface只是对行为进行抽象
2,跨域不同,抽象类体现的 是一种继承关系,父类的子类必须是is-a关系,父类和子类本质上是相同的。interface则不是,interface只是是实现者对行为的实现,比如说飞机和鸟实现飞的行为
3,设计层次不同。抽象类时自下而上设计的,我们要先知道子类才能抽象出父类,而接口不需要知道子类的存在,只需要定义规则就行。
区别的例子
定义一个phone的类,里面有打电话的方法,所有的手机都会有打电话的功能。
抽象类
abstract class Phone{
abstract void call();
}
接口
interface Phone{
void call();
}
现在增加一个功能“上网”surf,
抽象类变成了:
abstract class Phone{
abstract void call();
abstract void surf();
}
接口变为:
interface Phone{
void call();
void surf();
}
但是这样就有些问题出现了,phone中除了固定有的方法外还混进去了一个 surf功能,这样依赖于phone模块的就必学会上网,但是每个手机不一定都能上网(老年机)。这样就违反了设计原则,接口污染。
解决方法
一个使用接口,一个使用抽象类
abstract class Door{
abstract void open();
abstract void close();
}
interface Alarm{
void alarm();
}
class AlarmDoor extends Door implements Alarm{
void open(){}
void close(){}
void alarm(){}
}
这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实抽象类表示的是"is-a"关系,接口表示的是"like-a"关系。
总结
- 抽象类表示的是一种继承关系,只能单继承。接口表示的是一种行为规范,可以实现多个接口
- 抽象类可以拥有自己的成员变量和非抽象方法,接口中只能有静态常量,所有的方法都没有实现的
- 抽象类和接口的设计理念是不一样的,抽象类体现的是is-a关系,而接口代表的是like-a关系
抽象类和接口是java中两种不同的抽象概念,他们的存在对多态提供了好的支持,虽然他们之间语法上有很多相似性,但是他们的设计上往往体现了对问题的理解。只有对问题更好理解,才能更好设计接口和抽象类。
参考资料:作者: chenssy
出处: http://www.cnblogs.com/chenssy/