1. 语法上的区别(最基础的)

  • 抽象类:

    • abstract class声明。
    • 可以包含抽象方法(没有方法体)和具体方法。
    • 可以定义成员变量(可以是任意访问权限)。
    • 构造器​:有构造器,但不能直接new
  • 接口(JDK 8+):

    • interface声明。
    • 可以包含:抽象方法、默认方法(default修饰,有方法体)、静态方法(static修饰,有方法体)。
    • 成员变量默认是public static final的(常量)。
    • 没有构造器。

2. 本质上的区别(我自己的“顿悟”)

  • ​抽象类:​​ 表示的是一种 ​“is-a”​​ 关系,是一种​模板设计​。

    • ​例子:​Animal是一个抽象类,DogCat继承它。Dog是一个Animal。抽象类Animal可以定义所有动物共有的属性和行为(如name, eat(), sleep()),有些行为是具体的(sleep()),有些是抽象的(makeSound(),由子类实现)。
    • ​核心思想:​​ 代码复用。子类继承父类的功能,并实现或覆盖特定部分。
  • ​接口:​​ 表示的是一种 ​“has-a”​​ 或 “can-do” 关系,是一种​契约/规范​。

    • ​例子:​Flyable(会飞的)、Swimmable(会游泳的)是接口。一架Airplane(飞机)不是一种Bird(鸟),但它们都具有飞行的能力,所以都可以实现Flyable接口。
    • ​核心思想:​​ 定义行为规范,实现多态。一个类可以实现多个接口,从而具备多种能力。

3. 实战中如何选择?

  • ​当你关注事物本身的本质,需要强大的代码复用时,用抽象类。​​ 比如:各种业务单据(订单、入库单、出库单)可能有共同的流程处理逻辑。
  • ​当你关注事物的某个能力或行为,希望不相关的类也能具备此能力时,用接口。​​ 比如:一个Printer类需要实现Printable接口,一个Logger类也需要实现Printable接口来打印自己的状态,但它们本身没有继承关系。

一句话总结:

​“像”什么就用抽象类继承,“有”什么能力就用接口实现。​​ 在复杂的系统中,通常是抽象类定义核心骨架,接口定义扩展能力。

如果觉得我的文章对你有用,请随意赞赏