• 在面向对象编程(OOP)中,抽象类(Abstract Class)接口(Interface) 是两种定义类的方式,它们都可以用于定义规范,但它们有一些重要的区别。


    1. 抽象类(Abstract Class)

    定义

    • 抽象类是不能被实例化的类,通常包含至少一个抽象方法(没有方法体的函数)。
    • 主要用于提供基本实现,并允许子类继承。
    • 既可以包含普通方法(有方法体),也可以包含抽象方法(只有方法声明,没有方法体)。

    特点

    1. 不能实例化,只能被继承。
    2. 可以包含普通方法抽象方法
    3. 可以有成员变量(字段),可以定义构造函数。
    4. 可以有访问修饰符(public、protected、private)。

    示例(Java):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    abstract class Animal {
    String name;

    // 构造方法
    Animal(String name) {
    this.name = name;
    }

    // 具体方法
    void eat() {
    System.out.println(name + " is eating.");
    }

    // 抽象方法(子类必须实现)
    abstract void makeSound();
    }

    class Dog extends Animal {
    Dog(String name) {
    super(name);
    }

    @Override
    void makeSound() {
    System.out.println("Woof Woof!");
    }
    }

    public class Main {
    public static void main(String[] args) {
    Dog dog = new Dog("Buddy");
    dog.eat(); // 继承的普通方法
    dog.makeSound(); // 实现的抽象方法
    }
    }

    2. 接口(Interface)

    定义

    • 接口是一个完全抽象的类,所有方法默认都是抽象的(Java 8 之后支持默认方法)。
    • 主要用于定义行为规范,而不提供实现,由实现接口的类提供具体实现。

    特点

    1. 不能实例化,只能被类实现(implements)。
    2. 所有方法默认是 public abstract(即使不写 public abstract 关键字)。
    3. 不能包含普通方法(Java 8 之后可以有默认方法 default)。
    4. 不能有成员变量,但可以有 public static final 常量。
    5. 一个类可以实现多个接口(支持多继承)。

    示例(Java):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    interface Animal {
    // 默认是 public abstract
    void makeSound();
    }

    // 接口实现
    class Cat implements Animal {
    @Override
    public void makeSound() {
    System.out.println("Meow Meow!");
    }
    }

    public class Main {
    public static void main(String[] args) {
    Cat cat = new Cat();
    cat.makeSound();
    }
    }

    3. 主要区别

    对比项 抽象类 接口
    实例化 不能被实例化 不能被实例化
    方法 可以有普通方法和抽象方法 只能有抽象方法(Java 8+ 允许默认方法)
    成员变量 可以有变量(实例变量、静态变量) 只能有 public static final 常量
    构造函数 可以有构造函数 不能有构造函数
    继承关系 只能单继承(extends 可以多实现(implements
    使用场景 用于共享代码和定义行为 用于定义规范,让不同类实现相同行为

    4. 什么时候用?

    用抽象类

    • 当多个类有共同的部分实现(代码复用),但仍然需要在子类中提供具体实现时。
    • 当希望限制继承,只允许单一继承时。

    用接口

    • 当需要多个类具有相同行为,但它们本身可能没有共同的父类。
    • 当需要多继承时(Java 不支持类的多继承,但支持接口的多实现)。
    • 当需要定义一个严格的行为规范时。

    5. 结合使用

    有时候,可以结合 抽象类接口,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    interface Flyable {
    void fly();
    }

    abstract class Bird {
    void eat() {
    System.out.println("Bird is eating.");
    }

    abstract void makeSound();
    }

    // 继承抽象类 & 实现接口
    class Sparrow extends Bird implements Flyable {
    @Override
    void makeSound() {
    System.out.println("Chirp Chirp!");
    }

    @Override
    public void fly() {
    System.out.println("Sparrow is flying.");
    }
    }

    这里 Sparrow 继承 Bird(因为所有鸟都可以吃东西),但也实现了 Flyable 接口,因为不是所有鸟都会飞(如企鹅)。


    6. 结论

    • 抽象类 适用于父类提供部分实现,子类扩展功能的情况。
    • 接口 适用于定义行为规范,让多个不相关的类实现相同方法的情况。
    • 接口比抽象类更灵活,因为它允许多实现

    💡 记住:如果是**“是什么”(继承关系),用抽象类**;如果是**“能做什么”(行为规范),用接口**。