继承让代码复用,多态让代码灵活,接口让代码解耦。

目录


1. 继承

继承是面向对象的重要特性,允许子类复用父类的属性和方法。

1.1 基本继承

// 父类(超类、基类)
public class Animal {
    String name;
    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 + "正在睡觉");
    }
}

// 子类(派生类)
public class Dog extends Animal {
    String breed;  // 子类特有的属性
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类构造函数
        this.breed = breed;
    }
    
    public void bark() {  // 子类特有的方法
        System.out.println(name + "正在汪汪叫");
    }
    
    public void fetch() {
        System.out.println(name + "正在捡球");
    }
}

// 另一个子类
public class Cat extends Animal {
    boolean isIndoor;
    
    public Cat(String name, int age, boolean isIndoor) {
        super(name, age);
        this.isIndoor = isIndoor;
    }
    
    public void meow() {
        System.out.println(name + "正在喵喵叫");
    }
}

1.2 使用继承

public class InheritanceDemo {
    public static void main(String[] args) {
        // 创建Dog对象
        Dog dog = new Dog("旺财", 3, "金毛");
        dog.eat();      // 继承自Animal
        dog.sleep();    // 继承自Animal
        dog.bark();     // Dog特有方法
        dog.fetch();    // Dog特有方法
        
        System.out.println();
        
        // 创建Cat对象
        Cat cat = new Cat("咪咪", 2, true);
        cat.eat();      // 继承自Animal
        cat.sleep();    // 继承自Animal
        cat.meow();     // Cat特有方法
    }
}

1.3 方法重写(Override)

子类可以重写父类的方法:

public class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    public double area() {
        return 0;  // 基类默认实现
    }
    
    public void draw() {
        System.out.println("绘制一个" + color + "的图形");
    }
}

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制一个" + color + "的圆形,半径:" + radius);
    }
}

public class Rectangle extends Shape {
    private double width, height;
    
    public Rectangle(String color, double width, double height) {
        super(color);
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double area() {
        return width * height;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制一个" + color + "的矩形,宽:" + width + ",高:" + height);
    }
}

1.4 继承的注意事项

// 1. Java是单继承:一个类只能有一个父类
// class Child extends Parent1, Parent2 {}  // 编译错误!

// 2. 所有类都继承自Object类
// class MyClass {} 等价于 class MyClass extends Object {}

// 3. final类不能被继承
final class FinalClass {
    // 不能被继承
}

// 4. 构造函数不能被继承
// 子类必须调用父类构造函数(通过super)

2. 多态

多态是指同一个方法调用,根据对象的实际类型执行不同的代码。

2.1 方法多态

public class Animal {
    public void makeSound() {
        System.out.println("...");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪!");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵!");
    }
}

public class PolymorphismDemo {
    public static void main(String[] args) {
        // 多态:父类引用指向子类对象
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        
        // 同一个方法调用,不同的行为
        animal1.makeSound();  // 汪汪汪!
        animal2.makeSound();  // 喵喵喵!
        
        // 多态数组
        Animal[] animals = {new Dog(), new Cat()};
        for (Animal animal : animals) {
            animal.makeSound();
        }
    }
}

2.2 向上转型与向下转型

public class CastingDemo {
    public static void main(String[] args) {
        // 向上转型(自动):子类 → 父类
        Animal animal = new Dog("旺财", 3, "金毛");
        animal.eat();   // 可以调用父类方法
        animal.sleep(); // 可以调用父类方法
        // animal.bark();  // 编译错误!不能调用子类特有方法
        
        // 向下转型(强制):父类 → 子类
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;  // 强制转换
            dog.bark();              // 可以调用子类方法
            dog.fetch();
        }
        
        // Java 16+模式匹配
        if (animal instanceof Dog dog) {
            dog.bark();  // 直接使用,无需手动转换
        }
    }
}

3. 抽象类

抽象类是不能被实例化的类,用于定义通用模板。

3.1 抽象类和抽象方法

public abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // 抽象方法:只有声明,没有实现
    public abstract double area();
    public abstract double perimeter();
    
    // 普通方法:有实现
    public void display() {
        System.out.println("颜色:" + color);
        System.out.println("面积:" + String.format("%.2f", area()));
        System.out.println("周长:" + String.format("%.2f", perimeter()));
    }
}

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}

public class AbstractDemo {
    public static void main(String[] args) {
        // Shape shape = new Shape("红色");  // 编译错误!抽象类不能实例化
        
        Shape circle = new Circle("红色", 5);
        circle.display();
    }
}

4. 接口

接口是完全抽象的类型,定义了一组方法签名,但不提供实现。

4.1 定义接口

// 接口定义
public interface Drawable {
    // 常量(默认public static final)
    int MAX_SIZE = 100;
    
    // 抽象方法(默认public abstract)
    void draw();
    void resize(double factor);
    
    // 默认方法(Java 8+)
    default void drawWithBorder() {
        System.out.println("绘制边框");
        draw();
    }
    
    // 静态方法(Java 8+)
    static boolean isValidSize(int size) {
        return size > 0 && size <= MAX_SIZE;
    }
}

4.2 实现接口

public class Circle implements Drawable {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制圆形,半径:" + radius);
    }
    
    @Override
    public void resize(double factor) {
        radius *= factor;
    }
}

4.3 接口 vs 抽象类

特性 接口 抽象类
实例化 不能 不能
继承 多实现 单继承
构造函数 没有
成员变量 只能是常量 可以有变量
方法 抽象方法、默认方法、静态方法 抽象方法、普通方法
设计目的 定义"能做什么" 定义"是什么"

5. 实战案例

5.1 设计一个图形计算器

public abstract class Shape2D {
    protected String name;
    protected String color;
    
    public Shape2D(String name, String color) {
        this.name = name;
        this.color = color;
    }
    
    public abstract double area();
    public abstract double perimeter();
    
    public void display() {
        System.out.println("【" + name + "】颜色:" + color);
        System.out.println("面积:" + String.format("%.2f", area()));
        System.out.println("周长:" + String.format("%.2f", perimeter()));
    }
}

public class Circle2D extends Shape2D {
    private double radius;
    
    public Circle2D(String color, double radius) {
        super("圆形", color);
        this.radius = radius;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}

public class ShapeCalculator {
    private List<Shape2D> shapes = new ArrayList<>();
    
    public void addShape(Shape2D shape) {
        shapes.add(shape);
    }
    
    public void displayAll() {
        System.out.println("=== 图形列表 ===");
        for (Shape2D shape : shapes) {
            shape.display();
            System.out.println();
        }
    }
    
    public double getTotalArea() {
        return shapes.stream()
            .mapToDouble(Shape2D::area)
            .sum();
    }
}

6. 总结

本篇我们学习了:

继承:代码复用,extends关键字
多态:同一方法,不同行为
抽象类:模板方法,不能实例化
接口:完全抽象,多实现
类型转换:向上转型、向下转型

核心要点:

  1. 继承实现代码复用,多态实现灵活扩展
  2. 抽象类定义"是什么",接口定义"能做什么"
  3. 使用instanceof进行安全的向下转型
  4. 重写equals和hashCode时要成对重写

下一篇预告: 《Java从零到熟练(六):集合框架》

  • 学习List、Set、Map三大集合
  • 掌握集合的常用操作
  • 理解集合的选择策略

参考资源

  1. Java语言规范 - 继承
  2. Java教程 - 继承
  3. Java教程 - 接口

下一篇: Java从零到熟练(六):集合框架

更多推荐