2025.5.27

Interface(接口) vs Abstract Class(抽象类)对比

在面向对象编程(OOP)中,接口(Interface)抽象类(Abstract Class)都是用于实现多态和代码抽象的机制,但它们在设计目的和使用场景上有显著区别。以下是详细对比:


1. 核心区别

特性 接口(Interface) 抽象类(Abstract Class)
定义 纯抽象契约,仅声明方法(无实现)。 可包含抽象方法(无实现)和具体方法(有实现)。
多继承 一个类可实现多个接口(implements A, B)。 一个类只能继承一个抽象类(extends)。
成员变量 只能是 public static final(常量)。 可以是任意类型(实例变量、静态变量等)。
方法修饰符 默认 public abstract(Java 8+支持default方法)。 可包含 abstract、非抽象方法,甚至private方法。
构造方法 不能有构造方法。 可以有构造方法(用于子类初始化)。
设计目的 定义“能做什么”(行为契约)。 定义“是什么”(部分共性的抽象实现)。

2. 使用场景

何时用接口?

  • 需要定义跨继承树的行为契约(例如:SerializableComparable)。
  • 需要实现多重继承(一个类实现多个接口)。
  • 强调“has-a”关系(如:Bird implements Flyable)。

何时用抽象类?

  • 需要复用部分代码逻辑(抽象类可提供具体方法)。
  • 子类之间有明显的“is-a”继承关系(如:Dog extends Animal)。
  • 需要控制子类的初始化过程(通过构造方法)。

3. 代码示例

接口(Interface)

interface Flyable {
    void fly(); // 默认是 public abstract
    default void land() { // Java 8+ 的默认方法
        System.out.println("Landing...");
    }
}

class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("Bird is flying");
    }
}

抽象类(Abstract Class)

abstract class Animal {
    private String name;
    
    public Animal(String name) { // 构造方法
        this.name = name;
    }
    
    abstract void makeSound(); // 抽象方法
    
    public void eat() { // 具体方法
        System.out.println(name + " is eating");
    }
}

class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类构造方法
    }
    
    @Override
    void makeSound() {
        System.out.println("Woof!");
    }
}

4. Java 8+ 对接口的增强

  • 默认方法(Default Methods)
    允许接口提供默认实现,避免破坏现有代码(如Collection.stream())。
  • 静态方法(Static Methods)
    接口可以定义静态工具方法(如Comparator.comparing())。

5. 总结

选择依据 接口 抽象类
需要多重继承? ✅ 是 ❌ 否
需要共享代码实现? ❌ 否(Java 8后可通过default方法部分实现) ✅ 是
需要定义常量? ✅ 是(public static final ✅ 是(任意变量)
需要构造方法? ❌ 否 ✅ 是

经验法则

  • 优先使用接口:定义行为契约(如RunnableComparable)。
  • 使用抽象类:当多个子类有共享逻辑时(如模板方法模式)。
posted @ 2025-05-27 23:00  258333  阅读(80)  评论(0)    收藏  举报