首先看二者的区别
参数 | 抽象类 | 接口 |
默认的方法实现 | 它可以有默认的方法实现 | 接口完全是抽象的。它根本不存在方法的实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口方法默认修饰符是public。你不可以使用其它修饰符。 |
main方法 | 抽象方法可以有main方法并且我们可以运行它 | 接口没有main方法,因此我们不能运行它。(java8以后接口可以有default和static方法,所以可以运行main方法) |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
为什么要有抽象类?
假设我们定义一个动物类,一个猫类,一个狗类,猫类狗类都继承动物类。让我们实例化这些对象的时候有多种方法。
引用对象和实例化对象相同:
Cat cat = new Cat();
引用对象和实例化对象不同:
Animal cat = new Cat();
但是当我们这样写的时候却很奇怪
Animal animal = new Animal();
在这里我们实例化了一个动物对象,但是这个动物对象长什么样呢?很明显动物是抽象出来的,实例化一个动物对象并不合理,为了避免这种情况发生,可以把Animal对象标记为抽象的。当我们试图实例化一个抽象对象的时候编译器会报错,但是可以用这种抽象的类型作为引用类型。这也就是当初为何要有抽象类型的目的。
抽象类除了被继承之外,是没有用途,没有值,没有目的的。
接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。
抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如:猫,狗,这两个类(如果是类的话……),它们的抽象类是动物。
猫会叫,狗也会交,但是二者叫的声音并不一样,可以把 “叫” 定义成一个接口,然后让类去实现它。
所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。
当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的
虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。
总结
经过上面的讨论,我们得出两个结论:
- 抽象类和接口并不能互相替代。
- 抽象类和接口各有不可替代的作用。
在设计类的时候,首先考虑用接口抽象出类的特性,当你发现某些方法可以复用的时候,可以使用抽象类来复用代码。简单说,接口用于抽象事物的特性,抽象类用于代码复用。
当然,不是所有类的设计都要从接口到抽象类,再到类。程序设计本就没有绝对的范式可以遵循。上面的说法只是提供一个角度来理解抽象类和接口的关系,每个人都会有自己的理解,有人认为两者一点关系都没有,这也有道理。总之,模式和语法是死的,人是活的。
类可以实现很多个接口,但是只能继承一个抽象类
类可以不实现抽象类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
抽象类可以在不提供接口方法实现的情况下实现接口。
Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
参考博客:
https://blog.csdn.net/gongxiao1993/article/details/82055007
https://blog.csdn.net/fenglibing/article/details/2745123
《Head First Java》