07、多态 -- 面向对象的特性

1、多态(Polymorphism) 的定义


  • 一个 引用类型变量 可以指向 多种实际对象,这一点称为多态(polymorphism)。
    • 引用类型变量 在运行时能够自动地选择适当的方法,称为 动态绑定(dynamic binding)。
  • 这种多态也叫做:运行时多态

  • 多态 是一项让程序员“将 改变的事物未变的事物 分离 开来”的重要技术。
    • 可以 消除 类型 之间的 耦合关系提高代码的可扩展性复用性
  • 运行时多态 的 实现:方法的重写来实现的。
    • 父类引用可以指向子类对象,通过方法重写,根据子类不同,完成的功能不同
  • 核心机制 / 实现条件:
    • 1、向上转型(Upcasting)。
    • 2、动态绑定(Dynamic Binding)
    • 3方法重写(Override)
class Animal {
    void sound() {
        System.out.println("动物叫声");
    }
}

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

public class Main {
    public static void main(String[] args) {
        // 核心:父类引用指向子类对象
        Animal animal = new Dog();  // 向上转型
        animal.sound();             // 运行时调用 Dog 的 sound() → "汪汪汪"
    }
}

2、向上转型


  • 向上转型(Upcasting) 是指将 子类对象 赋值父类引用 的过程。
    • 这是 面向对象编程多态性 的核心体现。
    • 转型过程安全的 且由 编译器 自动完成(无需强制转换 )。

  • 局部变量 赋值中的 子类对象 赋值父类引用
// 子类
class Cat extends Animal {
    int age;

    public Cat(int age) {
        this.age = age;
    }

    @Override
    public void eat() {
        System.out.println("Cat is eating fish");
    }

    public static void main(String[] args) {
        // 向上转型(Upcasting)
        Animal animal = new Cat(3);
        // 输出的是 Animal 自己的 age 属性值。
        System.out.println(animal.age);
        // 调用的是 Cat 的 eat 方法。
        animal.eat();

        Cat cat = new Cat(3);
        // 输出的是 Cat 自己的 age 属性值。
        System.out.println(cat.age);
        // 调用的是 Cat 的 eat 方法。
        cat.eat();
    }
}

public class Animal {
    int age;
    public void eat() {
        System.out.println("Animal is eating");
    }
}

  • 策略模式:方法参数中的 向上转型
// 1. 定义策略接口(所有策略的通用行为)
interface PromotionStrategy {
    double applyPromotion(double price);
}

// 2. 实现具体策略类
// 满减策略
class FullReductionStrategy implements PromotionStrategy {
    @Override
    public double applyPromotion(double price) {
        if (price >= 200) return price - 50;  // 满200减50
        return price;
    }
}

// 折扣策略
class DiscountStrategy implements PromotionStrategy {
    @Override
    public double applyPromotion(double price) {
        return price * 0.8;  // 打8折
    }
}

// 无优惠策略
class NoPromotionStrategy implements PromotionStrategy {
    @Override
    public double applyPromotion(double price) {
        return price;
    }
}

// 3. 上下文类(负责使用策略)
class OrderContext {
    private PromotionStrategy strategy;

    // 通过构造器注入策略(也可用setter方法)-- 向上转型
    public OrderContext(PromotionStrategy strategy) {
        this.strategy = strategy;
    }

    public double calculateFinalPrice(double originalPrice) {
        return strategy.applyPromotion(originalPrice);
    }
}

// 4. 客户端使用
public class StrategyDemo {
    public static void main(String[] args) {
        // 创建订单,默认无优惠
        OrderContext order = new OrderContext(new NoPromotionStrategy());
        System.out.println("原价100,无优惠: " + order.calculateFinalPrice(100));  // 输出100.0

        // 动态切换为满减策略
        order = new OrderContext(new FullReductionStrategy());
        System.out.println("原价250,满减后: " + order.calculateFinalPrice(250)); // 输出200.0

        // 动态切换为折扣策略
        order = new OrderContext(new DiscountStrategy());
        System.out.println("原价100,8折后: " + order.calculateFinalPrice(100));   // 输出80.0
    }
}

  • 向上转型 vs 向下转型
特性向上转型向下转型
转型方向子类 → 父类父类 → 子类
安全性自动安全(编译器支持)需显式转换且可能抛出异常
典型用途实现多态、统一接口处理恢复子类特有功能

3、多态所需的支持

  • 多态这种特性也需要编程语言提供特殊的语法机制来实现。
    • 1、编程语言支持继承
    • 2、编程语言支持方法重写
    • 3、编程语言支持父类引用可以指向子类对象

4、多态的应用场景

  • 多态也是很多设计模式设计原则编程技巧 的代码实现基础。
    • 策略模式、基于接口非实现编程、依赖倒置原则里式替换原则、
    • 利用多态去掉冗长的 if-else 语句等等。
  • 使用父类方法的形参,实参可以是该父类的任意子类类型
  • 使用父类方法的返回值类型,返回值可以改父类的任意子类对象。

5、广义上的 其它类型的多态


1、编译时多态(静态多态)-- 通过方法的重载来实现的。


  • 在程序执行前,该方法就能够确定所在的类,此时由编译器或其它链接程序实现。
    • static 修饰的方法
    • final 修饰的方法
    • private 修饰的方法
  • 方法重载:
    • 在同一个类中,允许多个方法使用同一个名字,但是方法的参数不同,完成的功能不同
class Calculator {
    // 重载 add 方法
    int add(int a, int b) {
        return a + b;
    }
    double add(double a, double b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println(calc.add(2, 3));       // 调用 int 版本 → 5
        System.out.println(calc.add(2.5, 3.5));   // 调用 double 版本 → 6.0
    }
}

2、参数多态 / 泛型多态


  • 定义
    • 用泛型 (Generics) 实现代码对多种数据类型的通用操作,类型参数在编译时或运行时确定
  • 实现方式
    • 泛型类、泛型接口、泛型方法。
class Box<T> {
    private T content;
    void setContent(T content) {
        this.content = content;
    }
    T getContent() {
        return content;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setContent("Hello");
        Box<Integer> intBox = new Box<>();
        intBox.setContent(123);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值