java

继承、多态与接口

By AI-Writer 10 min read

继承、多态与接口

**继承(Inheritance)**是面向对象的核心机制之一,允许一个新类复用另一个类的属性和方法。**多态(Polymorphism)**则让同一操作作用于不同对象时产生不同的行为结果。**接口(Interface)**定义了行为的契约,是 Java 实现多态和解耦的重要工具。本文将深入讲解这三者的概念和使用方法。

继承的概念

继承允许在已有类的基础上创建新类,新类(子类)自动拥有父类的成员(属性和方法),同时可以添加自己特有的内容。

java
// 父类(基类 / 超类)
public class Animal {
    protected String name;   // protected:子类可访问
    protected int age;

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

    public void eat() {
        System.out.println(name + " 正在吃东西...");
    }

    public void sleep() {
        System.out.println(name + " 正在睡觉。");
    }
}
java
// 子类通过 extends 关键字继承父类
public class Dog extends Animal {
    private String breed;  // 子类独有的属性

    public Dog(String name, int age, String breed) {
        super(name, age);   // 调用父类构造器(必须在第一行)
        this.breed = breed;
    }

    // 子类新增方法
    public void bark() {
        System.out.println(name + " 汪汪叫!");
    }

    // 子类重写父类方法
    @Override
    public void eat() {
        System.out.println(name + "(" + breed + ")正在吃狗粮...");
    }
}
java
Dog dog = new Dog("旺财", 3, "金毛");
dog.eat();     // 旺财(金毛)正在吃狗粮...  (重写后的版本)
dog.sleep();   // 旺财 正在睡觉。            (继承自父类)
dog.bark();    // 旺财 汪汪叫!              (子类新增)

Java 的单继承限制:Java 中类只能继承一个父类,不能同时继承多个类(与 C++ 的多重继承不同)。但一个类可以实现多个接口。

super 关键字

super 用于在子类中访问父类的成员——调用父类构造器或父类方法:

java
public class Cat extends Animal {
    private boolean indoorCat;

    public Cat(String name, int age, boolean indoorCat) {
        super(name, age);   // 调用父类构造器
        this.indoorCat = indoorCat;
    }

    public void meow() {
        System.out.println(name + " 喵喵叫~");
    }

    @Override
    public void eat() {
        super.eat();        // 先调用父类方法
        System.out.println(name + " 吃完后舔了舔爪子。");
    }
}

方法重写(@Override)

子类可以**重写(Override)**父类的方法,用自己的实现替代父类的实现。@Override 注解是可选的,但强烈推荐使用——它让编译器帮你检查是否真的覆写了父类方法:

java
public class Bird extends Animal {
    public Bird(String name, int age) {
        super(name, age);
    }

    @Override   // 加上注解,编译器检查方法签名是否正确
    public void eat() {
        System.out.println(name + " 用喙啄食...");
    }

    // 新增:飞翔方法
    public void fly() {
        System.out.println(name + " 在天空中飞翔!");
    }
}

重写规则

  • 方法名、参数列表必须与父类完全相同
  • 返回类型可以是可以是父类返回类型的子类(协变返回类型)
  • 访问修饰符不能比父类更严格(父类 public → 子类不能 private
  • 不能重写 static 方法(隐藏,不是重写)
  • 不能重写 final 方法

多态

多态指同一类型的引用,在指向不同类型的对象时,调用相同方法产生不同行为。多态是 OOP 的核心优势,让代码更具灵活性和可扩展性。

父类引用指向子类对象

java
// 父类类型引用可以指向子类对象(向上转型,自动转换)
Animal a1 = new Dog("旺财", 3, "金毛");
Animal a2 = new Cat("小咪", 2, true);
Animal a3 = new Bird("小鹦", 1);

// 调用 eat(),实际执行的是各个子类重写后的版本
a1.eat();  // 旺财(金毛)正在吃狗粮...
a2.eat();  // 喵喵叫~ ...吃完后舔了舔爪子。
a3.eat();  // 小鹦 用喙啄食...

多态的条件

多态的发生需要满足三个条件:

  1. 存在继承关系——子类继承父类
  2. 子类重写父类方法——不同子类提供不同实现
  3. 父类引用指向子类对象——通过父类类型调用方法
java
// 多态数组:统一管理不同子类对象
Animal[] animals = {
    new Dog("旺财", 3, "金毛"),
    new Cat("小咪", 2, true),
    new Bird("小鹦", 1)
};

for (Animal animal : animals) {
    animal.eat();   // 每个对象调用自己的 eat() 实现
}
// 输出:
// 旺财(金毛)正在吃狗粮...
// 小咪 喵喵叫~
// 小鹦 用喙啄食...

向下转型与 instanceof

父类引用默认只能调用父类中声明的方法。如果需要调用子类特有的方法,需要进行向下转型(强制转换),并用 instanceof 做类型检查:

java
Animal animal = new Dog("旺财", 3, "金毛");

// animal.bark();  // 编译错误:Animal 类没有 bark() 方法

// 向下转型:先检查类型,再转换
if (animal instanceof Dog) {
    Dog dog = (Dog) animal;   // 强制转换为 Dog
    dog.bark();               // 旺财 汪汪叫!
}

// Java 16+ 支持带变量的 instanceof 模式匹配
if (animal instanceof Dog dog) {
    dog.bark();               // 直接使用 dog 变量,无需单独转型
}

接口

接口(Interface)是一种完全抽象的类型,只定义方法签名(不提供实现),由具体类去实现。接口是 Java 实现多重继承的主要手段——一个类可以实现多个接口。

定义接口

java
// 定义接口
public interface Swimmable {
    // 接口中的方法默认 public abstract(抽象方法)
    void swim();

    // Java 8+ 支持默认方法
    default void floatOnWater() {
        System.out.println("在水面上漂浮...");
    }
}

public interface Flyable {
    void fly();
}

实现接口

java
// 实现接口使用 implements 关键字
// 一个类可以实现多个接口(多重继承)
public class Duck extends Animal implements Swimmable, Flyable {
    public Duck(String name, int age) {
        super(name, age);
    }

    @Override
    public void swim() {
        System.out.println(name + " 在湖里游泳!");
    }

    @Override
    public void fly() {
        System.out.println(name + " 在天空中飞行!");
    }
}

接口的默认方法与静态方法

Java 8 为接口引入了默认方法(default)静态方法(static)

java
public interface Calculable {
    int calculate(int x, int y);

    // 默认方法:有默认实现,实现类可以直接使用或重写
    default int square(int x) {
        return x * x;
    }

    // 静态方法:属于接口本身,通过接口名调用
    static int triple(int x) {
        return x * 3;
    }
}

public class BasicCalculator implements Calculable {
    @Override
    public int calculate(int x, int y) {
        return x + y;  // 实现 calculate 方法
    }
}
java
BasicCalculator calc = new BasicCalculator();

System.out.println(calc.calculate(3, 5));   // 8(使用实现的方法)
System.out.println(calc.square(4));          // 16(使用默认方法)
System.out.println(Calculable.triple(4));    // 12(使用静态方法)

接口与抽象类的区别

特性接口抽象类
关键字interfaceabstract class
方法抽象方法;Java 8+ 可有 default/static抽象方法 + 普通方法
变量只能是 public static final 常量可以有各种属性
继承/实现类可以实现多个接口类只能继承一个抽象类
构造器不能有构造器可以有构造器
适用场景定义行为契约(“能做什么”)定义公共模板(“是什么”)

常见 JDK 内置接口

java
// java.lang.Comparable:定义对象自然顺序
public class Student implements Comparable<Student> {
    String name;
    int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student other) {
        return this.score - other.score;  // 按分数升序排列
    }
}

// Arrays.sort 使用 Comparable 接口排序
Student[] students = {
    new Student("Alice", 92),
    new Student("Bob", 78),
    new Student("Carol", 85)
};

Arrays.sort(students);
for (Student s : students) {
    System.out.println(s.name + ": " + s.score);
}
// Bob: 78
// Carol: 85
// Alice: 92

完整示例:支付系统

用多态和接口构建一个灵活的支付系统:

java
// 支付接口
public interface PaymentMethod {
    void pay(double amount);
    String getName();
}

// 微信支付
public class WeChatPay implements PaymentMethod {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付 ¥" + String.format("%.2f", amount));
    }

    @Override
    public String getName() {
        return "微信支付";
    }
}

// 支付宝
public class Alipay implements PaymentMethod {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付 ¥" + String.format("%.2f", amount));
    }

    @Override
    public String getName() {
        return "支付宝";
    }
}

// 购物车结账
public class ShoppingCart {
    private List<PaymentMethod> payments = new ArrayList<>();

    public void addPayment(PaymentMethod payment) {
        payments.add(payment);
    }

    public void checkout(double totalAmount) {
        System.out.println("===== 订单总额:¥" + totalAmount + " =====");
        for (PaymentMethod payment : payments) {
            System.out.print(payment.getName() + " → ");
            payment.pay(totalAmount);
        }
    }
}
java
ShoppingCart cart = new ShoppingCart();
cart.addPayment(new WeChatPay());
cart.addPayment(new Alipay());
cart.checkout(299.99);

// ===== 订单总额:¥299.99 =====
// 微信支付 → 使用微信支付 ¥299.99
// 支付宝 → 使用支付宝支付 ¥299.99

这个设计的优势:新增一种支付方式(如信用卡支付)只需新建一个类实现 PaymentMethod 接口,无需修改 ShoppingCart 的代码(开闭原则)。

小结

  • 继承通过 extends 实现子类复用父类成员;Java 只支持单继承
  • **方法重写(Override)**让子类提供父类方法的自定义实现;@Override 注解是最佳实践
  • 多态通过父类引用指向子类对象,使同一调用产生不同行为;使用 instanceof 做类型检查
  • 接口定义行为契约,支持类实现多个接口;Java 8+ 支持 default 和 static 方法
  • 抽象类 vs 接口:抽象类定义「是什么」的模板,接口定义「能做什么」的能力

继承、多态与接口是 Java 面向对象编程的三大支柱,理解它们才能写出结构清晰、易于扩展的代码。下一节我们将学习 Java 异常处理机制,掌握如何优雅地管理程序运行中的错误。

#java #继承 #多态 #接口 #抽象类 #Override

评论

A

Written by

AI-Writer

Related Articles

java
#6

Java 17+ 新特性精讲

全面讲解 Java 17 LTS 的核心新特性:Records、Sealed Classes、Pattern Matching for instanceof、Text Blocks、Switch Expressions,附详细代码示例

Read More