社交媒体

接口vs抽象类

接口vs抽象类

钩子:两个真实场景

场景一:写"动物"体系,每个动物都必须会 makeSound()——但"动物"这个类根本不该被 new 出来(你见过"一只动物"吗?)。我们需要一个不能实例化、只用来立规矩的类:抽象类。

场景二:要让订单能排序、能比较大小。但 Comparable 的规矩和"继承谁"无关——订单、学生、字符串都要能比。规矩应该能"嫁接"到任何类上:接口。

抽象类:半成品图纸

abstract class Animal {
    protected String name;

    public Animal(String name) { this.name = name; }

    public abstract void makeSound();   // 抽象方法:只有声明,没有方法体

    public void sleep() {               // 普通方法:可以有实现
        System.out.println(name + "在睡觉");
    }
}

三条规矩:

  1. abstract class 不能 new——半成品图纸造不了楼;
  2. 含抽象方法的类必须是抽象类;抽象类可以没有抽象方法(纯防 new 用);
  3. 子类必须重写全部抽象方法,否则子类也得声明为抽象类——规矩传给下一棒。

接口:纯粹的"能力合同"

interface Comparable2 {
    int compareTo(Object other);        // 天生 public abstract
}

interface Printable {
    void print();
}

// 一个类只能 extends 一个父类,但能 implements 多个接口
class Order implements Comparable2, Printable {
    private double amount;

    @Override
    public int compareTo(Object other) {
        Order o = (Order) other;
        return Double.compare(this.amount, o.amount);
    }

    @Override
    public void print() {
        System.out.println("订单金额:" + amount);
    }
}

接口是能力合同:签了合同(implements),就必须把合同上所有方法实现出来。类和接口的关系不再是"是一种",而是"能干什么"——Order 能比较、能打印,这些能力和"订单是什么"互相独立。

20-接口vs抽象类对比图.png

终极对比表(面试直接背)

对比项 抽象类 接口
关系 is-a(是什么) can-do(能干什么)
数量限制 单继承,一个爹 可实现多个
成员变量 任意 只能 public static final 常量
方法体 随便写 Java 8 前不行;之后可有 default/static
构造方法 有(给子类 super() 用) 没有
典型场景 动物→猫狗这类骨架复用 Comparable、Runnable 这类能力插头

选择口诀:是什么 → 抽象类;能干什么 → 接口。 还纠结时选接口——成本更低、组合更灵活,Java 官方新 API 也基本全用接口。

呼应回收

  • 第 16 篇说"第 20 篇你会第三次见到 this"——上面 Order.compareTo 里的 this.amount 就是第三次,参数 other 强转后也用了 this 区分;
  • 接口是多态的完美舞台:Comparable2 c = new Order(); 完全是第 19 篇"编译看左边,运行看右边"的复用。

模块三毕业小结

封装(守住数据)→ 继承(复用代码)→ 多态(一个接口多种行为)→ 抽象类/接口(立规矩)。四大件到齐,从下一篇开始进模块四:常用 API 与集合——第一个主角就是天天见的 String。


本文示例代码均已本地实测通过,可直接运行。
对应文件:InterfaceDemo.java


橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。