Appearance
🎭 多态
多态概述
多态(Polymorphism)是面向对象编程的三大特性之一,它允许同一个接口使用不同的实现,提高了代码的灵活性和可扩展性。
多态的类型
- 编译时多态:方法重载(Overload)
- 运行时多态:方法重写(Override)+ 向上转型
多态的特点
- 同一接口,不同实现:同一个方法调用,在不同对象上有不同行为
- 提高可扩展性:新增子类不影响现有代码
- 提高代码复用:通过父类引用统一处理子类对象
方法重载(编译时多态)
重载规则
- 方法名相同
- 参数列表不同(类型、数量、顺序)
- 返回类型可以不同(但仅返回类型不同不能构成重载)
重载示例
java
public class Calculator {
// 整数加法
public int add(int a, int b) {
return a + b;
}
// 浮点数加法(重载)
public double add(double a, double b) {
return a + b;
}
// 三个整数相加(重载)
public int add(int a, int b, int c) {
return a + b + c;
}
// 字符串连接(重载)
public String add(String a, String b) {
return a + b;
}
}
// 使用
Calculator calc = new Calculator();
calc.add(1, 2); // 调用 int add(int, int)
calc.add(1.0, 2.0); // 调用 double add(double, double)
calc.add(1, 2, 3); // 调用 int add(int, int, int)
calc.add("Hello", "World"); // 调用 String add(String, String)方法重写(运行时多态)
运行时多态示例
java
// 父类
public class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
public void move() {
System.out.println("动物在移动");
}
}
// 子类1
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗叫: 汪汪汪");
}
@Override
public void move() {
System.out.println("狗在跑");
}
}
// 子类2
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("猫叫: 喵喵喵");
}
@Override
public void move() {
System.out.println("猫在走");
}
}
// 使用
Animal animal1 = new Dog(); // 向上转型
Animal animal2 = new Cat(); // 向上转型
animal1.makeSound(); // 输出: 狗叫: 汪汪汪(运行时多态)
animal1.move(); // 输出: 狗在跑
animal2.makeSound(); // 输出: 猫叫: 喵喵喵(运行时多态)
animal2.move(); // 输出: 猫在走向上转型和向下转型
向上转型(Upcasting)
java
// 向上转型:子类对象赋值给父类引用
Animal animal = new Dog(); // Dog 向上转型为 Animal
// 可以调用父类中定义的方法
animal.makeSound(); // 调用 Dog 重写的方法
animal.move(); // 调用 Dog 重写的方法
// 不能调用子类特有的方法
// animal.bark(); // ❌ 编译错误向下转型(Downcasting)
java
// 向下转型:父类引用转换为子类引用
Animal animal = new Dog();
Dog dog = (Dog) animal; // 向下转型
// 现在可以调用子类特有的方法
dog.bark(); // ✅ 可以调用instanceof 检查
java
Animal animal = new Dog();
// 使用 instanceof 检查类型
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // 安全的向下转型
dog.bark();
}
// 更安全的写法
if (animal instanceof Dog dog) { // Java 14+ 模式匹配
dog.bark(); // 自动转换
}多态的应用
1. 统一接口处理
java
// 父类
public class Shape {
public double calculateArea() {
return 0;
}
}
// 子类
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
public class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
// 使用多态统一处理
Shape[] shapes = {
new Circle(5),
new Rectangle(4, 6),
new Circle(3)
};
// 统一调用,不同对象执行不同实现
for (Shape shape : shapes) {
System.out.println("面积: " + shape.calculateArea());
}2. 方法参数多态
java
public class AnimalService {
// 方法参数使用父类类型,可以接收任何子类对象
public void feed(Animal animal) {
animal.eat();
}
public void play(Animal animal) {
animal.move();
}
}
// 使用
AnimalService service = new AnimalService();
service.feed(new Dog()); // 可以传入 Dog 对象
service.feed(new Cat()); // 可以传入 Cat 对象
service.play(new Dog()); // 可以传入 Dog 对象3. 方法返回多态
java
public class AnimalFactory {
// 返回类型是父类,实际返回子类对象
public Animal createAnimal(String type) {
if ("dog".equals(type)) {
return new Dog();
} else if ("cat".equals(type)) {
return new Cat();
}
return null;
}
}
// 使用
AnimalFactory factory = new AnimalFactory();
Animal animal = factory.createAnimal("dog"); // 返回 Dog 对象
animal.makeSound(); // 调用 Dog 的方法抽象类与多态
抽象类
java
// 抽象类
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
// 抽象方法:必须由子类实现
public abstract void makeSound();
// 普通方法:可以有实现
public void eat() {
System.out.println(name + " 正在吃东西");
}
}
// 子类实现抽象方法
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " 叫: 汪汪汪");
}
}
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " 叫: 喵喵喵");
}
}接口与多态
java
// 接口
public interface Flyable {
void fly();
}
public interface Swimmable {
void swim();
}
// 实现接口
public class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("鸭子飞");
}
@Override
public void swim() {
System.out.println("鸭子游泳");
}
}
// 使用接口实现多态
Flyable flyable = new Duck();
flyable.fly();
Swimmable swimmable = new Duck();
swimmable.swim();多态的完整示例
java
// 员工管理系统
public abstract class Employee {
protected String name;
protected int id;
protected double baseSalary;
public Employee(String name, int id, double baseSalary) {
this.name = name;
this.id = id;
this.baseSalary = baseSalary;
}
// 抽象方法:计算工资(不同员工类型计算方式不同)
public abstract double calculateSalary();
// 普通方法
public void displayInfo() {
System.out.println("员工姓名: " + name);
System.out.println("员工ID: " + id);
System.out.println("基本工资: " + baseSalary);
System.out.println("实际工资: " + calculateSalary());
}
}
// 全职员工
public class FullTimeEmployee extends Employee {
private double bonus;
public FullTimeEmployee(String name, int id, double baseSalary, double bonus) {
super(name, id, baseSalary);
this.bonus = bonus;
}
@Override
public double calculateSalary() {
return baseSalary + bonus;
}
}
// 兼职员工
public class PartTimeEmployee extends Employee {
private int hours;
private double hourlyRate;
public PartTimeEmployee(String name, int id, double hourlyRate, int hours) {
super(name, id, 0); // 兼职员工没有基本工资
this.hourlyRate = hourlyRate;
this.hours = hours;
}
@Override
public double calculateSalary() {
return hourlyRate * hours;
}
}
// 使用多态
public class EmployeeManagement {
public static void main(String[] args) {
// 创建不同类型的员工
Employee[] employees = {
new FullTimeEmployee("张三", 1, 10000, 2000),
new PartTimeEmployee("李四", 2, 100, 80),
new FullTimeEmployee("王五", 3, 8000, 1500)
};
// 统一处理,多态体现
double totalSalary = 0;
for (Employee emp : employees) {
emp.displayInfo(); // 每个员工显示不同信息
totalSalary += emp.calculateSalary(); // 不同员工工资计算方式不同
System.out.println("---");
}
System.out.println("总工资支出: " + totalSalary);
}
}多态的优势
1. 提高代码可扩展性
java
// 添加新的员工类型,不需要修改现有代码
public class Contractor extends Employee {
private double contractAmount;
public Contractor(String name, int id, double contractAmount) {
super(name, id, 0);
this.contractAmount = contractAmount;
}
@Override
public double calculateSalary() {
return contractAmount;
}
}
// 可以直接使用,无需修改 EmployeeManagement 类2. 提高代码可维护性
java
// 修改某个子类的实现,不影响其他代码
public class FullTimeEmployee extends Employee {
@Override
public double calculateSalary() {
// 修改计算逻辑,不影响调用方
return baseSalary * 1.2 + bonus; // 新逻辑
}
}3. 统一接口处理
java
// 一个方法可以处理所有子类对象
public void processEmployee(Employee emp) {
emp.displayInfo();
double salary = emp.calculateSalary();
// 统一处理...
}多态的注意事项
1. 方法重写的规则
java
// ✅ 正确的重写
public class Parent {
public void method() { }
}
public class Child extends Parent {
@Override
public void method() { } // 正确
}
// ❌ 错误:不是重写(参数不同)
public class Child extends Parent {
public void method(int param) { } // 这是重载,不是重写
}2. 静态方法不能重写
java
public class Parent {
public static void staticMethod() {
System.out.println("Parent");
}
}
public class Child extends Parent {
public static void staticMethod() { // 不是重写,是隐藏
System.out.println("Child");
}
}
// 使用
Parent p = new Child();
p.staticMethod(); // 输出: Parent(不是 Child)3. 私有方法不能重写
java
public class Parent {
private void privateMethod() { } // 私有方法
}
public class Child extends Parent {
// 这不是重写,是新的方法
private void privateMethod() { }
}最佳实践
1. 使用父类引用
java
// ✅ 好的做法:使用父类引用
List<Animal> animals = new ArrayList<>();
animals.add(new Dog());
animals.add(new Cat());
// ❌ 不好的做法:使用具体类型
List<Dog> dogs = new ArrayList<>();
List<Cat> cats = new ArrayList<>();2. 优先使用接口
java
// ✅ 好的做法:使用接口
List<String> list = new ArrayList<>(); // 接口引用
// ❌ 不好的做法:使用具体类
ArrayList<String> list = new ArrayList<>(); // 具体类引用3. 使用抽象类定义通用行为
java
// ✅ 好的做法:抽象类定义通用行为
public abstract class Animal {
protected String name;
public abstract void makeSound(); // 子类必须实现
public void eat() { // 通用行为
System.out.println(name + " 正在吃");
}
}下一步
掌握了多态后,可以继续学习:
💡 提示:多态是面向对象编程的核心特性,理解多态有助于编写灵活、可扩展的代码
