接口和抽象类的区别,实不相瞒,我忘记了?
在Java基础部分,接口和抽象类是相当重要的知识点,尤其是接口,在后面的开发中,经常会见到这么四个字“面向接口编程”,而且对于接口和抽象类的知识也是面试中经常会被问到的,所以我们非常有必要熟练掌握这部分的知识!今天吗,我们就一起来回顾下!
小白: 庆哥,说真的,现在让我来说接口和抽象类的区别,我发现自己的记忆是模糊的,能说出来的大概就是:
接口和抽象类之间有相同也有不同,接口可以用来实现多实现,弥补继承的不足,接口使用关键字implements来实现接口,每一个实现接口的类都要实现其中的方法,而且接口中的方法默认都是public的,对于接口而言,不能有已经实现的方法,这个对于抽象类来说好像就可以,这好像就是两者的区别吧!
庆哥: 感觉你记得已经可以了,有的时候我们之所以会对某一个知识点的记忆产生模糊,一是自己不太理解,二是即使理解了,如果长时间不回顾,也是很容易忘记的,所以,复习,有的时候真的很重要!
小白: 是的,对于一个知识,我觉得首先就是有一个完整清晰的理解,然后再进行间断性的复习,巩固记忆,这样才会记忆的牢固。
庆哥: 可以啊,感觉你说出来学习的真谛啊!下面咱来一起回顾下接口和抽象类,以及他们的区别,或者说我们该怎么选择使用他们?
小白: 嗯嗯,我觉得首先要搞清楚的就是两者的概念了,什么是接口,什么是抽象类?我查了一下,找到这么些定义说明。
什么是接口?
接口,英文叫做interface,在Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常使用interface来声明,一个类通过实现接口的方式,从而来实现接口中的抽象方法。
什么是抽象类?
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
另外我还了解到对于接口,有这样的描述
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
对于抽象类有这样的描述
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
庆哥: 可以啊,你这功夫做的挺足啊,说的还很详细嘛我感觉我都没有什么好说的了,你这是在哪找的啊,总结的不错啊!
小白: 这是在菜鸟教程中找的,很适合我这种菜鸟啊!
庆哥: 哦哦,原来是在菜鸟教程啊,这个菜鸟教程还是不错的,总结的很到位,包含的也不仅仅有Java,是个自学的好地方!不过总结归总结,我们还需要一个个来,然后结合着代码来看,增加我们的印象,尤其是一些重点概念,我们先来看一下接口
接口
首先要知道接口如何定义
/**
* @author ithuangqing
*/
interface ITest {
/**
* 用来展示输出信息
*/
void show();
}
以上我们就定义了一个接口,在定义接口的时候我们可以注意一些细节,比如说不要这样写
/**
* @author ithuangqing
*/
public interface ITest {
/**
* 用来展示输出信息
*/
public abstract void show();
}
就是不要加任何修饰符,包括public,而且在接口中尽量不要定义变量,如果必须定义变量的话记住变量名一定要大写,像这样
/**
* @author ithuangqing
*/
interface ITest {
String NAME = "Java从0到1";
/**
* 用来展示输出信息
*/
void show();
}
以上我们就完美定义一个接口了
小白: 为什么要这样呢?
庆哥: 这就牵涉到接口的一些特点了,它有这么几点特性
- 使用interface修饰
- 接口中的所有方法都是公开的,并且是抽象方法
- 接口中可以定义成员变量,但都是公共静态常量
- 接口中不能存在实现的方法
- 实现了接口就必须实现接口中全部的方法
- 接口不是一个类,不能实例化
也就是说接口中的方法默认都是公共且抽象的,看下面几种写法
- Public abstract void a();
- Public void a();
- void a();
其实都是一样的效果,最终等同于第一种写法,所以为了保持代码的简洁性,因此不要加任何的修饰符,而对于变量,在接口中是不建议写变量的,如果非要写,那变量名统一大写,这是因为接口中的成员变量都是公共静态常量。
小白: 接口中不能有已经实现的方法吗?
庆哥: 是的,在接口中,是不能有实现的方法的,你看
看到这里已经报错了,所以在接口中是不存在已经实现的方法的。
小白: 嗯,接口不是一个类,不能被实例化,可以通过一个类去实现这个接口,然后实现接口中的方法来实现,这个接口中的方法要全部实现吧?
庆哥: 是的,实现了一个接口就要实现全部的方法。好了,接下来啊我们再来说一下抽象类吧
抽象类
首先要会定义一个抽象类
public abstract class AbstractPerson {
String name;
int age;
public abstract void show();
public void doMe(){
System.out.println("我是一个人");
}
}
这就定义了一个抽象类
小白: 我看你这个抽象类的命名是以Abstract开头,是不是抽象类的命名都这样命名呢?
庆哥: 一般推荐抽象类的命名以Abstract开头,便于判别是一个抽象类。
小白: 那这个抽象类不需要跟接口似的省略掉修饰符,以追求简洁吗?
庆哥: 这个我们通过代码来看,首先我们不加修饰符,是这样
public abstract class AbstractPerson {
abstract void show();
}
然后看它的继承类,实现方法之后是这样的、
/**
* 继承抽象类
*/
class Man extends AbstractPerson {
@Override
void show() {
}
}
然后再来看加上修饰符
public abstract class AbstractPerson {
public abstract void show();
}
然后再看继承类
/**
* 继承抽象类
*/
class Man extends AbstractPerson {
@Override
public void show() {
}
}
所以,对于抽象类我倒是建议加上修饰符,这样更加直观。
小白: 嗯嗯,知道了,那抽象类中可以有实现的方法吗?
庆哥: 我们可以来试一下就知道了
可以看到,在抽象类中是可以有实现的方法的,另外在抽象类中也是可以定义成员变量的,抽象类说到底还是一个类,跟接口是有区别的,对于抽象类,我们可以总结一下特点
- 使用abstract修饰作为抽象类和抽象方法
- 子类必须实现抽象类的抽象方法
- 那么就可以判断抽象类中的抽象方法不能是私有的,否则子类无法实现
- 抽象类是一个类,必然涉及到继承
- 抽象类中允许有实现的方法
抽象类和接口的区别
小白: 哦哦,到这里,我似乎可以总结一下两者的区别了
- 抽象类需要一个类去继承,接口则是需要去实现,并且都是要全部实现其中的抽象方法,两者皆是如此。
- 接口中不能有已经实现的方法,而抽象类则可以
- 接口可以多实现,但是抽象类只能单继承。
庆哥: 是的,总结的不错,我再补充几点
1. 抽象类里面是可以没有抽象方法的
2. 如果一个类,其中包含抽象方法,那么这个类一定是个抽象类
那么说到这里,你明白了到底什么是接口,什么是抽象类了吗?
小白: 经过上面的讨论学习,我感觉,接口更像是定义一种功能或者说操作,实现了这个接口就可以干某些事,而抽象类更像是对一些事物的高级概括。
庆哥: 你说的非常好,总的来说,接口的扩展性要比抽象类好很多,因为抽象类始终是一个类,注定只能单继承,不像接口可以多实现,就从灵活性和可扩展性而言,接口我们一般使用的较多!
小白: 经过这么讨论,我对接口和抽象类的认识更加深刻了,以后再经常复习,相信一定能很好的掌握这个知识,谢谢庆哥!
庆哥: 不谢,咱们是共同学习,一起进步,那今天就先到这啦!
Java从0到1,我们一起!完!