多态的体现与多种实现

Note: This article has been written with the assistance of AI.

多态的体现

多态是面向对象编程的三大特性之一,允许不同类的对象同一消息做出响应,提高了代码的灵活性可扩展性

方法重载

方法重载是指同一类中可以有多个同名方法方法签名是方法的唯一标识符,由方法名称参数列表(参数的类型、数量和顺序)组成,重载具有不同的参数列表(参数类型、数量或顺序不同)。虽然方法名相同,但根据传入的参数不同,编译器会在编译时确定调用哪个方法(方法重载的依据是编译器通过方法签名来区分重载的方法,编译时绑定编译器根据方法签名确定调用哪个方法)。

public class Calculator {
    
    // 整数加法
    public int add(int a, int b) {
        System.out.println("调用整数加法");
        return a + b;
    }
    
    // 浮点数加法 - 参数类型不同
    public double add(double a, double b) {
        System.out.println("调用浮点数加法");
        return a + b;
    }
    
    // 三个数加法 - 参数数量不同
    public int add(int a, int b, int c) {
        System.out.println("调用三参数加法");
        return a + b + c;
    }
    
    // 参数顺序不同
    public void printInfo(String name, int age) {
        System.out.println("姓名: " + name + ", 年龄: " + age);
    }
    
    public void printInfo(int age, String name) {
        System.out.println("年龄: " + age + ", 姓名: " + name);
    }
}

// 测试类
public class OverloadingDemo {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        
        // 编译器在编译时确定调用哪个方法
        System.out.println(calc.add(5, 10));        // 调用整数加法
        System.out.println(calc.add(5.5, 10.5));    // 调用浮点数加法
        System.out.println(calc.add(1, 2, 3));      // 调用三参数加法
        
        calc.printInfo("张三", 25);  // 姓名: 张三, 年龄: 25
        calc.printInfo(25, "张三");  // 年龄: 25, 姓名: 张三
    }
}

方法重写

方法重写是指子类重新定义父类中已有的方法,提供特定的实现。在运行时,JVM 会根据对象的实际类型来决定调用哪个版本的方法。

// 父类
class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    // 将被重写的方法
    public void makeSound() {
        System.out.println("动物发出声音");
    }
    
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
}

// 子类 Dog
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    // 重写父类方法
    @Override
    public void makeSound() {
        System.out.println(name + "汪汪叫");
    }
    
    // 子类特有的方法
    public void fetch() {
        System.out.println(name + "在接飞盘");
    }
}

// 子类 Cat
class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }
    
    // 重写父类方法
    @Override
    public void makeSound() {
        System.out.println(name + "喵喵叫");
    }
    
    // 重写父类方法
    @Override
    public void eat() {
        System.out.println(name + "优雅地吃鱼");
    }
}

// 测试类
public class OverridingDemo {
    public static void main(String[] args) {
        // 向上转型 - 父类引用指向子类对象
        Animal myDog = new Dog("旺财");
        Animal myCat = new Cat("咪咪");
        
        // 运行时多态 - JVM根据实际对象类型调用相应方法
        myDog.makeSound();  // 输出: 旺财汪汪叫
        myCat.makeSound();  // 输出: 咪咪喵喵叫
        
        myDog.eat();  // 输出: 旺财正在吃东西 (继承父类实现)
        myCat.eat();  // 输出: 咪咪优雅地吃鱼 (子类重写实现)
        
        // 多态在集合中的应用
        Animal[] animals = {new Dog("小黑"), new Cat("小白"), new Dog("大黄")};
        
        for (Animal animal : animals) {
            animal.makeSound();  // 运行时确定调用哪个方法
        }
    }
}

接口与实现

接口定义了一组方法规范,不同的类可以实现同一个接口并提供不同的实现,通过接口引用可以调用不同实现类的方法,使得程序在面对不同具体实现时保持一贯的调用方式。

// 定义接口
interface Shape {
    double calculateArea();
    double calculatePerimeter();
    void displayInfo();
}

// 圆形实现
class Circle implements Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
    
    @Override
    public void displayInfo() {
        System.out.printf("圆形 - 半径: %.2f, 面积: %.2f, 周长: %.2f%n", 
                         radius, calculateArea(), calculatePerimeter());
    }
}

// 矩形实现
class Rectangle implements 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;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * (width + height);
    }
    
    @Override
    public void displayInfo() {
        System.out.printf("矩形 - 宽: %.2f, 高: %.2f, 面积: %.2f, 周长: %.2f%n", 
                         width, height, calculateArea(), calculatePerimeter());
    }
}

// 测试类
public class InterfacePolymorphismDemo {
    public static void main(String[] args) {
        // 使用接口类型引用
        Shape circle = new Circle(5.0);
        Shape rectangle = new Rectangle(4.0, 6.0);
        
        // 相同的接口方法调用,不同的实现
        circle.displayInfo();
        rectangle.displayInfo();
        
        // 多态在集合中的应用
        Shape[] shapes = {
            new Circle(3.0),
            new Rectangle(2.0, 4.0),
            new Circle(7.0)
        };
        
        double totalArea = 0;
        for (Shape shape : shapes) {
            shape.displayInfo();
            totalArea += shape.calculateArea();
        }
        System.out.printf("所有图形的总面积: %.2f%n", totalArea);
    }
}

向上转型和向下转型:

  • 向上转型是自动进行的,将子类对象赋值给父类引用(父类类型的引用指向子类对象),这种方式可以在运行时期采用不同的子类实现。
// 父类
class Animal {
    public void eat() {
        System.out.println("动物在吃东西");
    }
    
    public void sleep() {
        System.out.println("动物在睡觉");
    }
}

// 子类
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗在吃狗粮");
    }
    
    public void bark() {
        System.out.println("狗在汪汪叫");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫在吃鱼");
    }
    
    public void meow() {
        System.out.println("猫在喵喵叫");
    }
}

public class UpcastingExample {
    public static void main(String[] args) {
        // 向上转型 - 自动进行
        Animal animal1 = new Dog();  // Dog对象转型为Animal类型
        Animal animal2 = new Cat();  // Cat对象转型为Animal类型
        
        animal1.eat();  // 输出: 狗在吃狗粮 (多态)
        animal1.sleep(); // 输出: 动物在睡觉
        
        animal2.eat();  // 输出: 猫在吃鱼 (多态)
        animal2.sleep(); // 输出: 动物在睡觉
        
        // animal1.bark(); // 编译错误! 父类引用无法调用子类特有方法
    }
}
  • 向下转型需要显式进行,并且有风险,需要使用instanceof进行检查。向下转型将父类引用转回其子类类型(执行前需要确认引用实际指向的对象类型以避免 ClassCastException)。
public class DowncastingExample {
    public static void main(String[] args) {
        // 向上转型
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        
        // 安全的向下转型 - 使用instanceof检查
        if (animal1 instanceof Dog) {
            Dog dog = (Dog) animal1;  // 向下转型
            dog.bark();  // 现在可以调用子类特有方法
            dog.eat();
        }
        
        if (animal2 instanceof Cat) {
            Cat cat = (Cat) animal2;  // 向下转型
            cat.meow();  // 现在可以调用子类特有方法
            cat.eat();
        }
        
        // 不安全的向下转型 - 会导致ClassCastException
        try {
            Dog wrongDog = (Dog) animal2;  // animal2实际上是Cat对象
            wrongDog.bark();
        } catch (ClassCastException e) {
            System.out.println("类型转换异常: " + e.getMessage());
        }
    }
}

Java 多态的多种实现方法

继承与方法重写

// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
    
    public void move() {
        System.out.println("动物在移动");
    }
}

// 子类重写方法
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
    
    @Override
    public void move() {
        System.out.println("狗在奔跑");
    }
    
    public void fetch() {
        System.out.println("狗在接飞盘");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
    
    @Override
    public void move() {
        System.out.println("猫在悄悄走动");
    }
}

class Bird extends Animal {
    @Override
    public void makeSound() {
        System.out.println("叽叽喳喳");
    }
    
    @Override
    public void move() {
        System.out.println("鸟在飞翔");
    }
}

public class InheritancePolymorphism {
    public static void main(String[] args) {
        // 多态表现:同一个方法调用,不同对象有不同行为
        Animal[] animals = {
            new Dog(),
            new Cat(),
            new Bird(),
            new Dog()
        };
        
        for (Animal animal : animals) {
            animal.makeSound();  // 运行时多态
            animal.move();       // 运行时多态
            System.out.println("---");
        }
        
        // 方法参数多态
        AnimalProcessor processor = new AnimalProcessor();
        processor.processAnimal(new Dog());
        processor.processAnimal(new Cat());
        processor.processAnimal(new Bird());
    }
}

class AnimalProcessor {
    // 方法参数使用父类类型,可以接受任何子类对象
    public void processAnimal(Animal animal) {
        System.out.println("处理动物:");
        animal.makeSound();
        animal.move();
        System.out.println("==========");
    }
}

接口实现

// 接口定义
interface Drawable {
    void draw();
    double getArea();
}

interface Resizable {
    void resize(double factor);
}

// 类实现接口
class Circle implements Drawable, Resizable {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制圆形,半径: " + radius);
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public void resize(double factor) {
        this.radius *= factor;
        System.out.println("圆形调整大小,新半径: " + radius);
    }
}

class Rectangle implements Drawable {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制矩形,宽度: " + width + ", 高度: " + height);
    }
    
    @Override
    public double getArea() {
        return width * height;
    }
}

class Triangle implements Drawable, Resizable {
    private double base;
    private double height;
    
    public Triangle(double base, double height) {
        this.base = base;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制三角形,底边: " + base + ", 高: " + height);
    }
    
    @Override
    public double getArea() {
        return 0.5 * base * height;
    }
    
    @Override
    public void resize(double factor) {
        this.base *= factor;
        this.height *= factor;
        System.out.println("三角形调整大小,新底边: " + base + ", 新高: " + height);
    }
}

public class InterfacePolymorphism {
    public static void main(String[] args) {
        // 接口引用指向实现类对象
        Drawable[] drawables = {
            new Circle(5.0),
            new Rectangle(4.0, 6.0),
            new Triangle(3.0, 4.0),
            new Circle(2.0)
        };
        
        System.out.println("=== 绘制所有图形 ===");
        for (Drawable drawable : drawables) {
            drawable.draw();
            System.out.println("面积: " + drawable.getArea());
            System.out.println("---");
        }
        
        // 多接口多态
        Resizable[] resizables = {
            new Circle(3.0),
            new Triangle(2.0, 3.0)
        };
        
        System.out.println("=== 调整图形大小 ===");
        for (Resizable resizable : resizables) {
            resizable.resize(1.5);  // 放大1.5倍
        }
        
        // 方法返回值的多态
        ShapeFactory factory = new ShapeFactory();
        Drawable shape1 = factory.createShape("circle");
        Drawable shape2 = factory.createShape("rectangle");
        
        shape1.draw();
        shape2.draw();
    }
}

class ShapeFactory {
    // 工厂方法返回接口类型,实现多态
    public Drawable createShape(String type) {
        switch (type.toLowerCase()) {
            case "circle":
                return new Circle(1.0);
            case "rectangle":
                return new Rectangle(2.0, 3.0);
            case "triangle":
                return new Triangle(2.0, 2.0);
            default:
                return new Circle(1.0);
        }
    }
}

抽象类

// 抽象类
abstract class Employee {
    protected String name;
    protected double baseSalary;
    
    public Employee(String name, double baseSalary) {
        this.name = name;
        this.baseSalary = baseSalary;
    }
    
    // 抽象方法 - 子类必须实现
    public abstract double calculateSalary();
    
    // 具体方法 - 子类可以继承或重写
    public void displayInfo() {
        System.out.println("员工姓名: " + name);
        System.out.println("基本工资: " + baseSalary);
        System.out.println("实发工资: " + calculateSalary());
    }
    
    // 模板方法模式 - 定义算法骨架
    public final void processSalary() {
        System.out.println("=== 处理 " + name + " 的工资 ===");
        calculateBase();
        calculateBonus();
        calculateDeduction();
        displayInfo();
        System.out.println();
    }
    
    protected void calculateBase() {
        System.out.println("计算基本工资: " + baseSalary);
    }
    
    protected abstract void calculateBonus();
    protected abstract void calculateDeduction();
}

// 具体子类
class FullTimeEmployee extends Employee {
    private double bonus;
    
    public FullTimeEmployee(String name, double baseSalary, double bonus) {
        super(name, baseSalary);
        this.bonus = bonus;
    }
    
    @Override
    public double calculateSalary() {
        return baseSalary + bonus;
    }
    
    @Override
    protected void calculateBonus() {
        System.out.println("全职员工奖金: " + bonus);
    }
    
    @Override
    protected void calculateDeduction() {
        double deduction = baseSalary * 0.1; // 10% 扣款
        System.out.println("社保扣款: " + deduction);
    }
}

class PartTimeEmployee extends Employee {
    private int hours;
    private double hourlyRate;
    
    public PartTimeEmployee(String name, int hours, double hourlyRate) {
        super(name, 0); // 基本工资为0,按小时计算
        this.hours = hours;
        this.hourlyRate = hourlyRate;
    }
    
    @Override
    public double calculateSalary() {
        return hours * hourlyRate;
    }
    
    @Override
    protected void calculateBonus() {
        System.out.println("兼职员工无奖金");
    }
    
    @Override
    protected void calculateDeduction() {
        System.out.println("兼职员工无扣款");
    }
    
    @Override
    public void displayInfo() {
        System.out.println("兼职员工姓名: " + name);
        System.out.println("工作小时: " + hours);
        System.out.println("时薪: " + hourlyRate);
        System.out.println("实发工资: " + calculateSalary());
    }
}

class Manager extends Employee {
    private double bonus;
    private double stockOptions;
    
    public Manager(String name, double baseSalary, double bonus, double stockOptions) {
        super(name, baseSalary);
        this.bonus = bonus;
        this.stockOptions = stockOptions;
    }
    
    @Override
    public double calculateSalary() {
        return baseSalary + bonus + stockOptions;
    }
    
    @Override
    protected void calculateBonus() {
        System.out.println("经理奖金: " + bonus);
    }
    
    @Override
    protected void calculateDeduction() {
        double deduction = baseSalary * 0.15; // 15% 扣款
        System.out.println("高级社保扣款: " + deduction);
    }
    
    @Override
    public void displayInfo() {
        System.out.println("经理姓名: " + name);
        System.out.println("基本工资: " + baseSalary);
        System.out.println("奖金: " + bonus);
        System.out.println("股票期权: " + stockOptions);
        System.out.println("实发工资: " + calculateSalary());
    }
}

public class AbstractClassPolymorphism {
    public static void main(String[] args) {
        Employee[] employees = {
            new FullTimeEmployee("张三", 8000, 2000),
            new PartTimeEmployee("李四", 40, 100),
            new Manager("王五", 15000, 5000, 3000),
            new FullTimeEmployee("赵六", 7000, 1500)
        };
        
        System.out.println("=== 员工工资处理 ===");
        for (Employee employee : employees) {
            employee.processSalary();  // 模板方法,多态表现
        }
        
        // 计算总工资支出
        double totalSalary = 0;
        for (Employee employee : employees) {
            totalSalary += employee.calculateSalary();
        }
        System.out.println("总工资支出: " + totalSalary);
    }
}

方法重载(编译时多态)

public class OverloadingPolymorphism {
    
    // 方法重载 - 编译时多态
    public void print(int num) {
        System.out.println("整数: " + num);
    }
    
    public void print(double num) {
        System.out.println("浮点数: " + num);
    }
    
    public void print(String text) {
        System.out.println("字符串: " + text);
    }
    
    public void print(int[] array) {
        System.out.print("数组: [");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]);
            if (i < array.length - 1) System.out.print(", ");
        }
        System.out.println("]");
    }
    
    public void print(String format, Object... args) {
        System.out.printf(format, args);
    }
    
    // 构造器重载
    private String name;
    private int age;
    
    public OverloadingPolymorphism() {
        this("未知", 0);
    }
    
    public OverloadingPolymorphism(String name) {
        this(name, 0);
    }
    
    public OverloadingPolymorphism(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public static void main(String[] args) {
        OverloadingPolymorphism poly = new OverloadingPolymorphism();
        
        // 方法重载多态
        poly.print(10);
        poly.print(3.14);
        poly.print("Hello");
        poly.print(new int[]{1, 2, 3, 4, 5});
        poly.print("姓名: %s, 年龄: %d%n", "张三", 25);
        
        // 构造器重载
        OverloadingPolymorphism obj1 = new OverloadingPolymorphism();
        OverloadingPolymorphism obj2 = new OverloadingPolymorphism("李四");
        OverloadingPolymorphism obj3 = new OverloadingPolymorphism("王五", 30);
    }
}

多态实现方法总结

实现方式 类型 特点
继承与方法重写 运行时多态 基于继承关系,子类重写父类方法
接口实现 运行时多态 基于接口契约,类实现接口方法
抽象类 运行时多态 包含抽象方法和具体方法
方法重载 编译时多态 同一类中方法名相同,参数不同
posted @ 2025-09-29 11:20  Charlie_Byte  阅读(11)  评论(0)    收藏  举报