在进行面向对象编程中,将某些共性的东西抽离出来的过程叫做抽象。在Java中抽象的实现主要有两种:抽象类和接口,下面简述两者的区别。
1. 定义的区别
接口
- 接口在Java中是一个抽象类型,是抽象方法的集合。
- 类可以实现一个或多个接口,实现接口的类必须实现接口中定义的所有方法。
- 接口使用
interface
关键字来定义,实现类通过implements
关键字来实现接口。
抽象类
- 当一个类没有足够的信息去描绘一个具体的对象时,这个类就是抽象类。
- 在Java中,抽象类可以包含非抽象方法。抽象类是一个没有具体实现其所有抽象方法的类,但是这并不意味着它不能包含非抽象方法。非抽象方法提供具体的实现,可以由子类继承或重写。
- 抽象类在
class
前加上abstract
关键字声明,其中的抽象方法也是在前面加上abstract
来修饰方法。子类继承抽象类用extends
来实现继承。(如果继承抽象类的子类是非抽象类,则必须重写抽象类中定义的抽象方法。)
2. 使用场景的区别
- 抽象类是对整个事物的抽象(包括了事物的属性和行为),而接口是对事物的局部行为进行抽象。
- 当需要提供一些默认实现时,使用抽象类更合适
- 当需要多个对象共同遵守某一项特性的时候,使用接口更合适。
3. 举例分析
- 飞行作为事物行为上的一种特性,我们可以用接口进行定义
public interface Fly {
void fly();
}
- 飞机和鸟作为整个事物的概念,都具有飞行这个行为,但各自具有不同的属性和其他方法行为,因此我们用抽象类进行定义
public abstract class Airplane implements Fly {
public abstract void refuel();
}
public abstract class Bird implements Fly {
public abstract void predation();
}
- 直升机和战斗机继承飞机的抽象类,并实现飞行和加油的抽象方法
public class Helicopter extends Airplane {
@Override
public void refuel() {
System.out.println("直升机加油!");
}
@Override
public void fly() {
System.out.println("直升机飞行!");
}
}
public class Fighter extends Airplane {
@Override
public void refuel() {
System.out.println("战斗机加油!");
}
@Override
public void fly() {
System.out.println("战斗机飞行!");
}
}
- 麻雀和老鹰继承鸟的抽象类,并实现捕食和飞行的抽象方法
public class Sparrow extends Bird {
@Override
public void predation() {
System.out.println("麻雀捕食!");
}
@Override
public void fly() {
System.out.println("麻雀飞行!");
}
}
public class Eagle extends Bird {
@Override
public void predation() {
System.out.println("老鹰捕食!");
}
@Override
public void fly() {
System.out.println("老鹰飞行!");
}
}
总结
- 抽象类可以看作是 is a 的关系,而接口可以看作是 has a 的关系。例如麻雀 is a 鸟,麻雀 has a 飞行的能力。