抽象类和接口的区别

面试中经常会问到这个问题,那么我们到底应该怎么回答呢?

语法方面

首先,在java语言中,抽象类和接口在语法方面就是有一些区别的,总结整理如下:

相同点

  1. 都是位于较上层的抽象层.
  2. 都不能被实例化.
  3. 都可以只声明方法,不实现.

不同点

  1. 抽象类可以有不抽象的方法,即某个方法有默认的实现,而接口不可以.
  2. 使用抽象类使用extends关键字集成,而接口使用implement关键字来实现.
  3. 抽象类可以有构造器,接口不可以.
  4. 抽象类里的方法可以使用public,protected,default等修饰符,接口的只可以是public.
  5. 抽象类可以有main方法,接口不可以.
  6. 继承抽象类的类必须实现所有抽象方法,否则自身也是抽象类,接口的实现类必须实现所有抽象方法.

设计思想方面

上面语法方面的知识重要吗?重要,不了解的话你无法使用它们.

但是上面的不同点足以让我们来判断在某一个场景下该使用哪个吗?

我觉得不是,我觉得使用他他们最重要的是设计思想方面.

假如,现在要设计一个Door的类.我们通过两种方式都可以实现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//抽象类
abstract class AbstractDoor {

public abstract void open();

public abstract void close();


}

//接口
interface Door {

void open();
void close();

}

这两种实现那种比较好一些?都还行,简单易懂.

那么这时候我们需要给添加报警功能,变成防盗门!怎么做呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstract class AbstractDoor {

public abstract void open();

public abstract void close();

public abstract String alarm();

}

interface Door {

void open();
void close();
void alarm();

}

将上述代码改成这样吗?这样好吗?

细想一下,门是一个实体,门的抽象类里面应该有报警功能吗?

因此,我们其实应该做的是这样的.

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class AbstractDoor {

public abstract void open();

public abstract void close();

}

interface Alarmable {

void alarm();

}

定义一个抽象类AbstractDoor,作为的基类,同时定义一个alarmable的接口.(alarmable是我自己写的,我不知道有没有这个单词,大家懂就好).

定义了一个门的抽象类,所有的门都必须有这两个方法.(不能开关的叫什么门啊!),同时定义了一个可报警的接口,当我们需要一个防盗门的时候,只需要继承AbstractDoor,同时实现Alarmable的接口,这样就拥有了这三个方法.

同时,这样做的扩展性极好,当你发现门应该多一个共同的方法时,比如,锁住,你可以在AbstractDoor中扩展,当你需要一个可以报警的窗户的时候,你可以实现Alarmable接口.岂不是美滋滋.

面试中如何回答我不敢给出正确答案,但是我认为,代码是写给人看的,所以你需要正确的设计以及正确的命名,来让代码的阅读者一看便懂,而不是深陷与语法,毕竟语法可以被创造.否则,我们需要抽象类和接口的区别干什么?直接将所有项目中用到的方法一股脑塞进一个类不就好了.

注意事项

本文的区别仅限于通俗意义上的区别.

另外,在java8中,Oracle已经开始尝试向接口中引入默认方法和静态方法,以此来减少抽象类和接口在语法上的差异。在java8之后,我们可以为接口提供默认实现的方法并且不用强制子类来实现它.有兴趣的胖友可以移步这里查看一哈.Java8 接口的静态方法和默认方法.


完。



ChangeLog

2018-11-18 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com

更多学习笔记见个人博客——>呼延十