Java多态

1. 什么是多态?

  • 多态在Java里其实就是“同一条指令,不同的对象给出不同的反应”。多态的前提是类的继承和方法的重写。编译时类型和运行时类型不一致,编译时看左边,运行时看右边。体现了一种开闭原则OCP(对扩展开放,对修改关闭)。

2. Java中实现多态的方式有哪些?

2.1 方法重载

  • 方法重载(overloading):在同一个类中,方法名相同但参数列表不同。编译器根据调用方法时传入的参数类型和个数决定调用哪个方法。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Calculator {
    public int add(int a, int b) {
    return a + b;
    }

    public double add(double a, double b) {
    return a + b;
    }
    }

2.2 方法重写

  • 方法重写(overriding):在继承关系中,子类重写父类的方法,方法名、参数列表和返回类型必须相同,访问权限不能更严格。运行时根据对象的实际类型决定调用哪个方法。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Animal {
    public void makeSound() {
    System.out.println("Animal makes a sound");
    }
    }

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

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

    public class Main {
    public static void main(String[] args) {
    // 编译看左边,运行看右边
    Animal animal1 = new Dog();
    Animal animal2 = new Cat();
    animal1.makeSound(); // Output: Dog barks
    animal2.makeSound(); // Output: Cat meows
    }
    }

3. 为什么需要多态?

  • 在开发中,设计一个变量、或方法形参、返回值类型时,无法确定它具体的类,只能确定它是某个类型
  • 多态使得调用者不需要关心对象的具体类型,使用父类作为方法的形参,即使增加了新的子类方法也无需改变,提高了扩展性,符合开闭原则。

4. 示例

  • 比如一个支付系统。现在支持支付宝和微信支付,未来还会支持银行卡、云闪付、数字人民币,那就可以先定义一个抽象能力:

    1
    2
    3
    interface PayService {
    void pay(double amount);
    }
  • 然后分别实现不同的支付方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class AliPay implements PayService {
    public void pay(double amount) {
    System.out.println("使用支付宝支付 " + amount);
    }
    }

    class WechatPay implements PayService {
    public void pay(double amount) {
    System.out.println("使用微信支付 " + amount);
    }
    }
  • 业务代码里就一句:

    1
    2
    3
    public void checkout(PayService payService, double money) {
    payService.pay(money); // 多态在这里发生魔法
    }
  • 调用时只需要提供对象:

    1
    2
    checkout(new AliPay(), 100);
    checkout(new WechatPay(), 200);