Skip to content

多态

对象多态:将方法的形参定义为父类类型,这个方法可以接收该父类的任意子类对象;形参既能接受狗,也能接收猫,对象多态; 行为多态:同一个方法具有不同的表现形式或形态的能力;同一个 eat 方法,有不同的表现,即行为多态;

1

多态前提

  • 有继承或者实现关系
  • 有方法重写
  • 有父类引用指向子类对象

1

java
package com.ruoyi.system.test;

public class PolymorphismDemo {
    public static void main(String[] args) {

        /**
         * ## 多态前提:
         * - 有继承或者实现关系
         * - 有方法重写
         * - 有父类引用指向子类对象
         *
         * 多态的成员访问特点:
         *
         * 成员变量:编译看左边(父类),运行看左边(父类)
         *          因为是父类的引用,所以访问存在局限性,只能访问super空间中的数据
         *
         * 成员方法:编译看左边(父类),运行看右边(子类)
         *          编译时检查方法在父类中是否存在,不存在则编译报错;存在则编译通过,但是运行时执行子类的方法
         *          为什么运行看右边,因为父类中定义的方法如果是抽象方法,运行父类中的方法没有任何意义
         *
         * 静态成员:编译看左边(父类),运行看左边(父类)
         *          static 修饰的成员,推荐使用类型调用
         *          即使对象调用,在字节码文件中 还是被改为类名调用   f.show() ---> 字节码文件中     --> Fu.show()
         *          所以父类调方法,肯定使用父类的逻辑
         * 静态方法随类,没有Override
         */

//        子类引用指向子类对象
        Zi zi = new Zi();

        System.out.println(zi.num); //20
        zi.show(); //子类方法 show

//        父类引用指向子类对象(以多态的形式创建了对象)
        Fu fu = new Zi();
        System.out.println(fu.num); //10
        fu.show(); //子类方法 show

//        接口类型变量,指向了实现类对象也是多态的形式
        Inter inter = new InterImpl();
    }
}

interface Inter {
    void show();
}


class Fu {
    int num = 10;
    public void show() {
        System.out.println("父类方法 show");
    }
}

class Zi extends Fu {
    int num = 20;
    @Override
    public void show() {
        System.out.println("子类方法 show");
    }
}

class InterImpl implements Inter {
    @Override
    public void show() {
        System.out.println("show()方法被调用");
    }
}

多态的好处:提高代码的扩展性

  • 方法的形参定义为父类类型,就可以传入该类的任意子类对象了;
java
// 定义动物父类
abstract class Animal {
    public abstract void makeSound();
}

// 狗类继承动物类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪!");
    }
}

// 猫类继承动物类
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵!");
    }
}

// 动物表演类
class AnimalShow {
    // 使用父类类型作为参数,可以接收任何Animal的子类对象
    public static void perform(Animal animal) {
        System.out.print("动物表演节目:");
        animal.makeSound(); // 调用实际对象的重写方法
    }
}

// 测试类
public class PolymorphismTest {
    public static void main(String[] args) {
        // 可以传入Dog对象
        AnimalShow.perform(new Dog()); // 输出:动物表演节目:汪汪汪!

        // 也可以传入Cat对象
        AnimalShow.perform(new Cat()); // 输出:动物表演节目:喵喵喵!

        // 如果以后增加了新的动物子类,比如Bird,这个方法也能直接使用
        // AnimalShow.perform(new Bird()); // 无需修改现有代码
    }
}

多态的弊端:不能调用子类特有的成员变量和成员方法;

java
// 父类
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}

// 子类,拥有父类没有的方法和属性
class Dog extends Animal {
public int age = 5; // 子类特有属性

    public void eat() {
        System.out.println("狗吃骨头");
    }

    // 子类特有方法
    public void watchHouse() {
        System.out.println("狗看家");
    }

}

// 测试类
public class PolymorphismLimitation {
public static void main(String[] args) {
// 多态形式创建对象
Animal animal = new Dog();

        // 可以调用父类中存在的方法
        animal.eat(); // 正常执行

        // 无法直接访问子类特有的属性
        // System.out.println(animal.age); // 编译错误!父类中没有age属性

        // 无法直接调用子类特有的方法
        // animal.watchHouse(); // 编译错误!父类中没有watchHouse方法
    }

}

多态中的转型

1

  • 需要向下转型
  • ClassCaseException: 类型转换异常 原因:在强转过程中,如果目标类型和实际类型,不是同一种类型,就会出现异常 instanceof: 判断左边的变量,记录的是不是右边的类型

编译看左边,编译阶段就报错,左边的父类没有; 怎么解决弊端,多态的转型;

小的给大的,子给父,能直接赋值; 大的给小的, 需要加括号 强转;

java
// 父类
class Animal {
    public void eat() {
        System.out.println("动物吃饭");
    }
}

// 子类,拥有特有方法
class Dog extends Animal {
    public void eat() {
        System.out.println("狗吃骨头");
    }

    // 子类特有方法
    public void watchHouse() {
        System.out.println("狗看家");
    }
}

// 猫类
class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

// 测试转型
public class PolymorphismCast {
    public static void main(String[] args) {
        // 向上转型(自动):子类转父类
        Animal animal = new Dog(); // 小的给大的,直接赋值

        // 调用父类存在的方法
        animal.eat(); // 输出:狗吃骨头(动态绑定)

        // 向下转型(强制):父类转子类,需要强转才能调用子类特有方法
        Dog dog = (Dog) animal; // 大的给小的,需要强转
        dog.watchHouse(); // 现在可以调用子类特有方法了

        // 使用instanceof避免ClassCastException
        if (animal instanceof Dog) {
            Dog dog2 = (Dog) animal;
            dog2.watchHouse();
        }

        // 错误的转型示例
        // Animal cat = new Cat();
        // Dog wrongDog = (Dog) cat; // ClassCastException!猫不能转成狗
    }
}

多态案例:模拟订单

java
package com.ruoyi.system.order;

public interface OrderService {

    /**
     * 创建订单
     */
    void create();

    /**
     * 查询订单
     */
    void findOne();

    /**
     * 查询订单列表
     */
    void findList();

    /**
     * 取消订单
     */
    void cancel();

    /**
     * 订单完成
     */
    void finish();

    /**
     * 支付订单
     */
    void paid();
}
java
package com.ruoyi.system.order;

public class OrderServiceImpl implements OrderService {
    @Override
    public void create() {
        System.out.println("创建订单");
    }

    @Override
    public void findOne() {
        System.out.println("查询订单");
    }

    @Override
    public void findList() {
        System.out.println("查询订单列表");
    }

    @Override
    public void cancel() {
        System.out.println("取消订单");
    }

    @Override
    public void finish() {
        System.out.println("完成订单");
    }

    @Override
    public void paid() {
        System.out.println("支付订单");
    }
}
java
package com.ruoyi.system.order;

public class OverseasImpl implements OrderService {
    public void check(){
        System.out.println("ip地址检测");
    }

    @Override
    public void create() {
        System.out.println("海外订单--创建");
    }

    @Override
    public void findOne() {
        System.out.println("海外订单--查询");
    }

    @Override
    public void findList() {
        System.out.println("海外订单--查询列表");
    }

    @Override
    public void cancel() {
        System.out.println("海外订单--取消");
    }

    @Override
    public void finish() {
        System.out.println("海外订单--完成");
    }

    @Override
    public void paid() {
        System.out.println("海外订单--支付");
    }
}
java
package com.ruoyi.system.order;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
       Scanner scanner = new Scanner(System.in);

       System.out.println("请输入订单类型:1.普通订单 2.海外订单");

       int orderType = scanner.nextInt();

        OrderService orderService = null;

       switch (orderType) {
           case 1:
               orderService = new OrderServiceImpl(); // 对象多态

               break;
           case 2:
               orderService = new OverseasImpl();

               OverseasImpl overseas = (OverseasImpl) orderService; // 强转 父强转给子;强转成自己的类型 那不就能调了

//               特有方法
               overseas.check();
               break;

           }


        // 行为多态
        orderService.create();
        orderService.findOne();
        orderService.findList();
        orderService.cancel();
        orderService.finish();
        orderService.paid();

    }
}

Copyright ©2025 moweiwei