第 8 章:抽象类与接口
学习目标
- 理解抽象类和接口的本质区别
- 掌握 abstract / interface / implements 关键字
- 学会选择:什么时候用抽象类,什么时候用接口
一、抽象类(abstract)
抽象类 = 不能实例化、专门用来被继承的类。
java
public abstract class Shape {
public abstract double area(); // 抽象方法:只有声明,没有实现
public void printInfo() { // 普通方法:可以有实现
System.out.println("面积:" + area());
}
}
// Shape s = new Shape(); // ❌ 不能实例化抽象类子类必须实现所有抽象方法(除非子类也是抽象类):
java
public class Circle extends Shape {
private double radius;
public Circle(double radius) { this.radius = radius; }
@Override
public double area() { // 必须实现父类的抽象方法
return Math.PI * radius * radius;
}
}二、接口(interface)
接口 = 行为的抽象(能力清单)。Java 8+ 支持默认方法和静态方法。
java
public interface Flyable {
int MAX_HEIGHT = 10000; // 隐式 public static final
void fly(); // 隐式 public abstract(必须实现)
default void land() { // Java 8+:默认方法(可不实现)
System.out.println("降落");
}
static boolean canFly(Flyable f) { // Java 8+:静态方法
return f != null;
}
}类用 implements 实现接口,可多实现:
java
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟在飞");
}
}
public class Duck implements Flyable, Swimmable, Runnable { // 多实现
@Override public void fly() { }
@Override public void swim() { }
@Override public void run() { }
}三、抽象类 vs 接口(怎么选)
| 维度 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract class | interface |
| 继承/实现 | 单继承(extends) | 多实现(implements) |
| 字段 | 可以是任何字段 | 只能是 public static final |
| 方法 | 抽象+普通+构造器 | 抽象+默认+静态(JDK 8+) |
| 设计意图 | "是什么"(is-a) | "能做什么"(has-a) |
选择规则:
java
// ✅ 抽象类:同一类族的共性(如 Animal → Dog/Cat)
abstract class Animal { abstract void sound(); }
class Dog extends Animal { ... }
// ✅ 接口:跨类族的共同能力(如 Bird / Airplane 都能 Fly)
interface Flyable { void fly(); }
class Bird implements Flyable { ... }
class Airplane implements Flyable { ... }⚠️ 坑 1:接口的字段默认
public static final,不能改:javainterface MyInterface { int MAX = 100; } // MyInterface.MAX = 200; // ❌ final 不能改
⚠️ 坑 2:
default方法多实现时可能冲突:javainterface A { default void hello() { System.out.println("A"); } } interface B { default void hello() { System.out.println("B"); } } class C implements A, B { // ❌ 编译报错:需要显式重写 hello() @Override public void hello() { A.super.hello(); } // 显式选一个 }
四、实战:策略模式
接口 + 组合,比继承更灵活:
java
interface DiscountStrategy {
double apply(double price);
}
class VipDiscount implements DiscountStrategy {
public double apply(double price) { return price * 0.8; }
}
class HolidayDiscount implements DiscountStrategy {
public double apply(double price) { return price * 0.7; }
}
class Order {
private DiscountStrategy strategy;
public void setStrategy(DiscountStrategy strategy) { // 运行时切换策略
this.strategy = strategy;
}
public double checkout(double price) {
return strategy.apply(price);
}
}
// 使用
Order order = new Order();
order.setStrategy(new VipDiscount());
System.out.println(order.checkout(100)); // 80
order.setStrategy(new HolidayDiscount());
System.out.println(order.checkout(100)); // 70五、本章小结
| 要点 | 关键 |
|---|---|
| 抽象类 | 不能实例化,可包含抽象方法和普通方法 |
| 接口 | 行为的抽象,Java 8+ 支持 default / static 方法 |
| 多实现 | 一个类可实现多个接口(逗号分隔) |
| 选择 | 共性用抽象类(is-a),能力用接口(has-a) |
| default 冲突 | 多接口 default 同名需显式重写 |
动手练习
- Shape 抽象类:Shape → Circle / Rectangle,各自实现
area()和perimeter() - Flyable 接口:Bird / Airplane / Superman 实现
fly(),写一个makeThemFly(Flyable[])方法 - 策略模式:写一个
PaymentStrategy接口(Alipay / WeChatPay),Order 类持有策略引用
下一章:第 9 章:枚举与内部类 →