-
前言
到目前为止,看起来接口与抽象类很像,他们里面都有抽象方法,都不能实例化。但其实他们的含义及其想解决的问题都是截然不同的,本文将从两个方面介绍他们之间的区别。
一、语法上的不同
接口与抽象类语法上有很大不同,体现了接口比抽象类更具有灵活性,选择性更大的特点。
对比 | 接口 | 抽象类 |
声明 | interface | abstract class |
成员变量 | 没有变量,其成员无论怎样去定义,都是公共常量——公有的、最终的、静态的。即使不显示标识,编译器也会自动加上。 | 抽象类的成员变量则是完全依据显示定义的不同而不同,编译器不会做任何动作,没有任何强制限制。 |
方法 | 所有接口中均隐含为共有的和抽象的,即使不显示修饰,编译器也会自动加上,接口中不能有非抽象方法,其方法一定不能是静态的、最终的或公有的。 | 编译器不会为抽象类中的方法添加任何修饰符,这完全取决于开发人员,可以有抽象方法,也可以没有抽象方法,但只要有一个方法是抽象的,该类就必须为抽象类,若有抽象方法,该方法不能为最终的、静态的或私有的 |
继承 | 接口可以继承自多个来自不同继承树上的接口,但是其只能继承自接口,不能继承自类。继承后,不能设计其父接口中的方法,接口不能实现别的接口,也就是定义接口时不能出现implements关键字 | 抽象类只能继承一个父类,但可以实现多个接口,其可以选择性的设计父类或父类接口中的抽象方法 |
多态 | 接口类型的引用可以指向任何实现自该接口或实现自该接口的子接口中的类,通过接口引用可以访问其指向的对象中实现自接口中的方法 | 抽象类的引用可以指向其子类的对象,通过该引用可以访问子类中继承自该抽象类的所有属性和方法 |
二、具体的含义不同
接口与抽象类在具体含义上有很大不同,抽象类更注重其是什么及其本质;而接口不是,接口更注重其具有什么样的功能及其充当什么样的角色。
例如,可以飞的事物有很多,如飞机、鸟或超人。但是飞机是个机械工具,需要汽油,而鸟与超人是实质动物,需要进食。所以,鸟可以继承自动物,但其可以扮演飞行器的角色。例:
package cahpter05;
//创建飞行器接口
interface Flyer
{
//所有继承Flyer接口的类都必须实现该方法
public void fly();
}
//创建动物抽象类,动物类中有一个进食方法,且为抽象方法
abstract class Animal
{
public abstract void eat();
}
//创建机器抽象类,有一个consume方法,该方法也为抽象方法
abstract class Vehicle
{
public abstract void consum();
}
//创建飞机抽象类,该类继承自机器类,实现了飞行器接口,并且实现了从抽象父类和接口过来的抽象方法
class AirPlan extends Vehicle implements Flyer
{//实现方法
public void consum()
{
System.out.println("消耗汽油的飞行器!");
}
public void fly()
{
System.out.println("我是飞机!");
}
}
//创建鸟类,鸟类继承自动物类,实现飞行器接口
class Bird extends Animal implements Flyer
{
public void eat()
{
System.out.println("鸟需要吃东西!");
}
public void fly()
{
System.out.println("我是一只鸟!");
}
}
public class Sample5_1
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Bird b=new Bird();
AirPlan air=new AirPlan();
System.out.println("*****飞机执行的动作*****");
air.fly();
air.consum();
System.out.println("*****鸟执行的动作*****");
b.fly();
b.eat();
}
}
从结果可以看出,飞机与鸟都有相同之处,都可以飞,也就是都是先了飞行器这个接口。但是飞机与鸟之间有本质的区别,即其没有任何的继承关系,一个是机械,一个是动物。
由此可见,接口的实现与抽象类的继承的含义是不同的,应该站在不同的角度看待这两个概念,一个是物体的本质,而另一个则是物体可以充当的角色。