前言:

        在面向对象编程中,继承实现了代码的复用,而多态则让代码更具拓展性和灵活性。多态(Polymorphism)——“多种形态”,指的是同一行为在不同对象上表现出不同的结果。

        例如:让猫和狗都执行“吃”这个动作,猫吃鱼,狗吃骨头。这就是多态的直观体现。

本文将从多态的概念开始,详细解析Java中多态的实现条件,方法重写规则,向上/向下转型,动态绑定机制,多态的优缺点。

目录

前言:

一.多态的概念

1.1多态的实现条件

1.2代码示例:

二.方法重写(Override)

2.1重写规则:

2.2重写vs重载

2.3重写的设计原则

三.向上转型与向下转型

3.1向上转型(Upcasting)

3.2向下转型(Downcasting)

四.动态绑定和静态绑定

五.多态的优缺点

5.1优点一:降低圈复杂度,避免大量的if-else

5.2优点二:可拓展能力强

5.3       缺点

总结


一.多态的概念

        多态:通俗来说:就是去完成某个行为,当不同对象去完成时会产生不同状态。

1.1多态的实现条件

        在Java中实现条件,必须满足以下三个条件,缺一不可:

1.必须在继承体系下(有父子类关系)

2.子类必须要对父类中的方法重写

3.通过父类的引用调用重写的方法

多态的体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。

1.2代码示例:

//父类Animal
public class Animal{
    String name;
    int age;
    public Animal(String name,int age){
        this.name=name;
        this.age=age;
    }

    public void eat(){
        System.out.println(name+"吃饭");
    }
}

//子类Cat
public class Cat{
    public void Cat(String name,int age){
        super(name,age);
    }

    @Override
    public void eat(){
        System.out.println(name+"吃鱼");
    }
}

// 子类 Dog
public class Dog extends Animal {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name + "吃骨头~~~");
    }
}

//测试
public class Test{
    //形参为父类自用,可以接受任何子类对象

    public static void eat(Animal a){
        a.eat();
    }
 public static void main(String[] args) {
        Cat cat = new Cat("元宝", 2);
        Dog dog = new Dog("小七", 1);

        eat(cat);  // 元宝吃鱼
        eat(dog);  // 小七吃骨头~~~
}

关键点:eat(Animal a)方法在编写时并不知道传入的具体是Cat还是Dog,只有在程序运行时,根据实际传入的对象类型,才决定调用哪个eat方法。这就是运行时多态

二.方法重写(Override)

        重写:子类对父类的非静态,非private,非final,非构造方法的实现过程进行重写编写。外壳不变,核心重写。

2.1重写规则:

规则 说明
方法名,参数列表,返回值类型

必须完全一致(返回值类型可以是子类类型

——协变返回类型)

访问权限

不能比父类中被重写的方法的访问权限更低

(父类是public,子类不能是protected)

异常 不能抛出比父类更宽泛的检擦异常
不能被重写的方法 static,private,final修饰的方法,以及构造方法
注解 使用@Override

2.2重写vs重载

对比点 重写(Override) 重载(Overload)
发生范围 子类和父类之间 同一个类中
方法名 必须相同 必须相同
参数列表 必须相同 必须不同(个数,类型,顺序)
返回值 相同或子类类型(协变) 可以不同
访问权限 不能更严格 无要求
修饰符 不能是static/private/final 无要求
绑定时机 运行时(动态绑定) 编译时(静态绑定)

2.3重写的设计原则

        对于已经投入使用的类,尽量不要修改。可以新建以一个类,重写需要改变的方法。

例如:旧手机来电只显示号码,新手机需要显示头像和地区。不应该修改老手机类(避免影响仍在使用的客户),而是创建新手机类,重写来电方法。

三.向上转型与向下转型

3.1向上转型(Upcasting)

        创建一个子类对象,将其当成父类对象来使用。

语法:        父类类型    对象名    =   new   子类类型  ()

使用场景:直接赋值

                方法传参(上面的eat(Animal a))

                方法返回(返回父类类型,实际返回子类对象)

public static Animal buyAnimal(String var) {
    if ("狗".equals(var)) {
        return new Dog("狗狗", 1);
    } else if ("猫".equals(var)) {
        return new Cat("猫猫", 1);
    }
    return null;
}

优点:让代码实现更简单灵活

缺点:不能调用子类特有的方法

3.2向下转型(Downcasting)

        将向上转型后的父类引用还原为子类对象,以便调用子类特有的方法。

Animal animal = new Cat("元宝", 2);
// animal.bark(); // 编译错误,Animal 中没有 bark
Cat cat = (Cat) animal;  // 向下转型
cat.mew();  // 可以调用 Cat 特有的方法

风险:如果转型失败,运行时抛出ClassCastException

Animal animal = new Dog("小七", 1);
Cat cat = (Cat) animal;  // 编译通过,但运行时报错!

安全转换:使用instanceof关键字判断。

if(animal instanceof Cat){
    Cat cat=(Cat) animal;
    cat.new();
}

instanceof用于判断对象是否是某个类(或其子类)的实例,返回true后再转型是安全的。

四.动态绑定和静态绑定

        静态绑定:编译时就能确定调用的方法。典型带面:方法重载,static方法,private方法,final方法。

        动态绑定:编译时不确定,运行时根据实际对象类型决定调用的方法。典型代表:多态下的重写方法。

五.多态的优缺点

5.1优点一:降低圈复杂度,避免大量的if-else

        假设我们需要绘制多个形状(圆形,矩形,花朵)。如果不适用多态,代码会充斥if-else:

public static void drawShapes() {
    Rect rect = new Rect();
    Cycle cycle = new Cycle();
    Flower flower = new Flower();
    String[] shapes = {"cycle", "rect", "cycle", "rect", "flower"};

    for (String shape : shapes) {
        if (shape.equals("cycle")) {
            cycle.draw();
        } else if (shape.equals("rect")) {
            rect.draw();
        } else if (shape.equals("flower")) {
            flower.draw();
        }
    }
}

使用多态后,代码变得简洁:

public static void drawShapes() {
    Shape[] shapes = {new Cycle(), new Rect(), new Cycle(), new Rect(), new Flower()};
    for (Shape shape : shapes) {
        shape.draw();  // 多态:每个形状自己知道怎么画
    }
}

圈复杂度:粗略等于代码中条件语句和循环语句的个数。多态显著降低圈复杂度,提升代码可读性和可维护性。

5.2优点二:可拓展能力强

        如果新增一个Triangle形状,多态方式只需要新增类

class Triangle extends Shape {
    @Override
    public void draw() {
        System.out.println("△");
    }
}
// 在数组中直接添加 new Triangle() 即可

5.3       缺点

        代码可读性略有下降(需要理解继承和重写关系)

        性能上有损耗(动态绑定需要额外查找)

        不能调用子类特有的方法(需要向下转型,有风险)

总结

        

核心概念 要点
多态条件 继承+重写+父类引用调用子类对象
重写规则

方法签名一直,访问权限不能更加严格

不能用static/private/final

向上转型 子类对象赋给父类引用,灵活但丢失子类特有方法
向下转型 强制转回子类,需要instanceof保证安全
动态绑定 运行时确定调用哪个方法,是多态的基础
多态优点 构造方法中调用可重写的方法

        多态是java面向对象三大特性之一(封装,继承,多态)。

更多推荐